1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_gl_replayer.cpp
27 #include "vogl_gl_replayer.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_sync_object.h"
30 #include "vogl_trace_file_writer.h"
31 #include "vogl_texture_format.h"
32 #include "gl_glx_replay_helper_macros.inc"
33 #include "vogl_backtrace.h"
35 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
36 #include "vogl_miniz.h"
38 #include "vogl_timer.h"
39 #include "vogl_file_utils.h"
41 #include "vogl_vector.h"
43 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC 129
44 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC 0x12345678
45 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC -999999.0f
47 //----------------------------------------------------------------------------------------------------------------------
48 // glInterleavedArrays helper table
49 //----------------------------------------------------------------------------------------------------------------------
50 struct interleaved_array_desc_entry_t
66 #define _2f (sizeof(GLfloat) * 2)
67 #define _3f (sizeof(GLfloat) * 3)
68 #define _4f (sizeof(GLfloat) * 4)
69 #define _5f (sizeof(GLfloat) * 5)
70 #define _6f (sizeof(GLfloat) * 6)
71 #define _7f (sizeof(GLfloat) * 7)
72 #define _8f (sizeof(GLfloat) * 8)
73 #define _9f (sizeof(GLfloat) * 9)
74 #define _10f (sizeof(GLfloat) * 10)
75 #define _11f (sizeof(GLfloat) * 11)
76 #define _12f (sizeof(GLfloat) * 12)
77 #define _15f (sizeof(GLfloat) * 15)
78 #define _c (sizeof(GL_UNSIGNED_BYTE) * 4)
80 static const interleaved_array_desc_entry_t vogl_g_interleaved_array_descs[] =
82 // format et ec en st sc sv tc pc pn pv s
83 { GL_V2F, false, false, false, 0, 0, 2, 0, 0, 0, 0, _2f },
84 { GL_V3F, false, false, false, 0, 0, 3, 0, 0, 0, 0, _3f },
85 { GL_C4UB_V2F, false, true, false, 0, 4, 2, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _2f },
86 { GL_C4UB_V3F, false, true, false, 0, 4, 3, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _3f },
87 { GL_C3F_V3F, false, true, false, 0, 3, 3, GL_FLOAT, 0, 0, _3f, _6f },
88 { GL_N3F_V3F, false, false, true, 0, 0, 3, 0, 0, 0, _3f, _6f },
89 { GL_C4F_N3F_V3F, false, true, true, 0, 4, 3, GL_FLOAT, 0, _4f, _7f, _10f },
90 { GL_T2F_V3F, true, false, false, 2, 0, 3, 0, 0, 0, _2f, _5f },
91 { GL_T4F_V4F, true, false, false, 4, 0, 4, 0, 0, 0, _4f, _8f },
92 { GL_T2F_C4UB_V3F, true, true, false, 2, 4, 3, GL_UNSIGNED_BYTE, _2f, 0, _c + _2f, _c + _5f },
93 { GL_T2F_C3F_V3F, true, true, false, 2, 3, 3, GL_FLOAT, 0, _2f, _5f, _8f },
94 { GL_T2F_N3F_V3F, true, false, true, 2, 0, 3, 0, 0, _2f, _5f, _8f },
95 { GL_T2F_C4F_N3F_V3F, true, true, true, 2, 4, 3, GL_FLOAT, _2f, _6f, _9f, _12f },
96 { GL_T4F_C4F_N3F_V4F, true, true, true, 4, 4, 4, GL_FLOAT, _4f, _8f, _11f, _15f }
113 #define VOGL_INTERLEAVED_ARRAY_SIZE (sizeof(vogl_g_interleaved_array_descs) / sizeof(vogl_g_interleaved_array_descs[0]))
115 //----------------------------------------------------------------------------------------------------------------------
116 // vogl_replayer::vogl_replayer
117 //----------------------------------------------------------------------------------------------------------------------
118 vogl_gl_replayer::vogl_gl_replayer()
120 m_swap_sleep_time(0),
121 m_dump_framebuffer_on_draw_prefix("screenshot"),
122 m_screenshot_prefix("screenshot"),
123 m_dump_framebuffer_on_draw_frame_index(-1),
124 m_dump_framebuffer_on_draw_first_gl_call_index(-1),
125 m_dump_framebuffer_on_draw_last_gl_call_index(-1),
126 m_ctypes_packet(&m_trace_gl_ctypes),
127 m_trace_pointer_size_in_bytes(0),
128 m_trace_pointer_size_in_uints(0),
129 m_temp_gl_packet(&m_trace_gl_ctypes),
130 m_temp2_gl_packet(&m_trace_gl_ctypes),
131 m_pCur_gl_packet(NULL),
133 m_pending_make_current_packet(&m_trace_gl_ctypes),
134 m_pending_window_resize_width(0),
135 m_pending_window_resize_height(0),
136 m_pending_window_resize_attempt_counter(false),
139 m_last_parsed_call_counter(-1),
140 m_last_processed_call_counter(-1),
141 m_cur_trace_context(0),
142 m_cur_replay_context(NULL),
143 m_pCur_context_state(NULL),
144 m_frame_draw_counter(0),
145 m_frame_draw_counter_kill_threshold(cUINT64_MAX),
147 m_pBlob_manager(NULL),
148 m_pPending_snapshot(NULL),
149 m_delete_pending_snapshot_after_applying(false),
150 m_replay_to_trace_remapper(*this)
154 m_trace_gl_ctypes.init();
157 //----------------------------------------------------------------------------------------------------------------------
158 // vogl_replayer::~vogl_replayer
159 //----------------------------------------------------------------------------------------------------------------------
160 vogl_gl_replayer::~vogl_gl_replayer()
167 //----------------------------------------------------------------------------------------------------------------------
168 // vogl_replayer::init
169 //----------------------------------------------------------------------------------------------------------------------
170 bool vogl_gl_replayer::init(uint flags, vogl_replay_window *pWindow, const vogl_trace_stream_start_of_file_packet &sof_packet, const vogl_blob_manager &blob_manager)
177 if ((!pWindow) || (!pWindow->is_opened()))
183 if ((sof_packet.m_pointer_sizes != sizeof(uint32)) && (sof_packet.m_pointer_sizes != sizeof(uint64_t)))
185 vogl_error_printf("%s: Invalid trace pointer size (%u)\n", VOGL_METHOD_NAME, m_sof_packet.m_pointer_sizes);
189 m_pBlob_manager = &blob_manager;
193 m_sof_packet = sof_packet;
194 m_trace_pointer_size_in_bytes = m_sof_packet.m_pointer_sizes;
195 m_trace_pointer_size_in_uints = m_sof_packet.m_pointer_sizes / sizeof(uint);
197 m_trace_gl_ctypes.init();
198 m_trace_gl_ctypes.change_pointer_sizes(m_trace_pointer_size_in_bytes);
200 if (!m_pWindow->is_opened())
202 const uint initial_window_width = 1024;
203 const uint initial_window_height = 768;
204 if (!m_pWindow->open(initial_window_width, initial_window_height))
206 vogl_error_printf("%s: Failed opening window!\n", VOGL_METHOD_NAME);
211 m_pCur_gl_packet = NULL;
215 m_last_parsed_call_counter = 0;
216 m_last_processed_call_counter = 0;
218 m_pending_make_current_packet.clear();
219 m_pending_window_resize_width = 0;
220 m_pending_window_resize_height = 0;
221 m_pending_window_resize_attempt_counter = 0;
223 m_at_frame_boundary = true;
225 m_cur_trace_context = 0;
226 m_cur_replay_context = 0;
227 m_pCur_context_state = NULL;
231 m_frame_draw_counter = 0;
232 m_frame_draw_counter_kill_threshold = cUINT64_MAX;
239 //----------------------------------------------------------------------------------------------------------------------
240 // vogl_replayer::deinit
241 //----------------------------------------------------------------------------------------------------------------------
242 void vogl_gl_replayer::deinit()
246 destroy_pending_snapshot();
249 // TODO: Make a 1st class snapshot cache class
250 for (uint i = 0; i < m_snapshots.size(); i++)
251 vogl_delete(m_snapshots[i].m_pSnapshot);
254 m_ctypes_packet.reset();
256 m_pCur_gl_packet = NULL;
260 m_last_parsed_call_counter = 0;
261 m_last_processed_call_counter = 0;
263 m_pending_make_current_packet.clear();
264 m_pending_window_resize_width = 0;
265 m_pending_window_resize_height = 0;
266 m_pending_window_resize_attempt_counter = 0;
268 m_at_frame_boundary = true;
270 m_cur_trace_context = 0;
271 m_cur_replay_context = 0;
272 m_pCur_context_state = NULL;
274 m_frame_draw_counter = 0;
275 m_frame_draw_counter_kill_threshold = cUINT32_MAX;
277 m_pBlob_manager = NULL;
280 m_swap_sleep_time = 0;
281 m_dump_framebuffer_on_draw_prefix = "screenshot";
282 m_screenshot_prefix = "screenshot";
283 m_backbuffer_hash_filename.clear();
284 m_dump_framebuffer_on_draw_frame_index = -1;
285 m_dump_framebuffer_on_draw_first_gl_call_index = -1;
286 m_dump_framebuffer_on_draw_last_gl_call_index = -1;
288 m_dump_frontbuffer_filename.clear();
293 //----------------------------------------------------------------------------------------------------------------------
294 // vogl_gl_replayer::dump_trace_gl_packet_debug_info
295 //----------------------------------------------------------------------------------------------------------------------
296 void vogl_gl_replayer::dump_trace_gl_packet_debug_info(const vogl_trace_gl_entrypoint_packet &gl_packet)
300 vogl_debug_printf("Trace packet: Total size %u, Param size: %u, Client mem size %u, Name value size %u, call %" PRIu64 ", ID: %s (%u), Thread ID: 0x%" PRIX64 ", Trace Context: 0x%" PRIX64 "\n",
302 gl_packet.m_param_size,
303 gl_packet.m_client_memory_size,
304 gl_packet.m_name_value_map_size,
305 gl_packet.m_call_counter,
306 g_vogl_entrypoint_descs[gl_packet.m_entrypoint_id].m_pName,
307 gl_packet.m_entrypoint_id,
308 gl_packet.m_thread_id,
309 gl_packet.m_context_handle);
312 //----------------------------------------------------------------------------------------------------------------------
313 // vogl_gl_replayer::dump_packet_as_func_call
314 //----------------------------------------------------------------------------------------------------------------------
315 void vogl_gl_replayer::dump_packet_as_func_call(const vogl_trace_packet& trace_packet)
321 if (!trace_packet.pretty_print(str, false))
322 vogl_error_printf("%s: packet pretty print failed!\n", VOGL_METHOD_NAME);
324 vogl_debug_printf("%s\n", str.get_ptr());
327 //----------------------------------------------------------------------------------------------------------------------
328 // vogl_replayer::process_next_packet
329 //----------------------------------------------------------------------------------------------------------------------
330 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(const vogl_trace_packet &gl_packet)
332 // TODO: Fix const correctness
333 return process_gl_entrypoint_packet((vogl_trace_packet &)gl_packet);
336 //----------------------------------------------------------------------------------------------------------------------
337 // vogl_replayer::process_next_packet
338 //----------------------------------------------------------------------------------------------------------------------
339 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(vogl_trace_file_reader &trace_reader)
343 vogl_trace_file_reader::trace_file_reader_status_t read_status = trace_reader.read_next_packet();
344 if (read_status == vogl_trace_file_reader::cEOF)
346 vogl_message_printf("At trace file EOF\n");
349 else if (read_status != vogl_trace_file_reader::cOK)
351 vogl_error_printf("Failed reading from trace file\n");
352 return cStatusHardFailure;
355 status_t status = cStatusOK;
357 switch (trace_reader.get_packet_type())
364 case cTSPTGLEntrypoint:
366 if (!m_temp_gl_packet.deserialize(trace_reader.get_packet_buf().get_ptr(), trace_reader.get_packet_buf().size(), false))
368 vogl_error_printf("Failed deserializing GL entrypoint packet\n");
369 status = cStatusHardFailure;
373 status = process_next_packet(m_temp_gl_packet);
379 vogl_message_printf("Encountered EOF packet in trace file\n");
380 status = cStatusAtEOF;
385 vogl_error_printf("Encountered unknown packet type in trace file\n");
386 status = cStatusSoftFailure;
393 vogl_error_printf("%s: %s failure processing GL entrypoint packet\n", VOGL_METHOD_NAME, (status == cStatusHardFailure) ? "Hard" : "Soft");
399 //----------------------------------------------------------------------------------------------------------------------
400 // vogl_replayer::process_pending_window_resize
401 //----------------------------------------------------------------------------------------------------------------------
402 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_window_resize(bool *pApplied_snapshot)
406 if (pApplied_snapshot)
407 *pApplied_snapshot = false;
409 status_t status = cStatusOK;
411 if (get_has_pending_window_resize())
413 status = process_frame_check_for_pending_window_resize();
414 if (status != cStatusOK)
418 if (m_pPending_snapshot)
420 if (pApplied_snapshot)
421 *pApplied_snapshot = true;
423 status_t status = process_applying_pending_snapshot();
424 if (status != cStatusOK)
431 //----------------------------------------------------------------------------------------------------------------------
432 // vogl_replayer::process_frame
433 //----------------------------------------------------------------------------------------------------------------------
434 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame(vogl_trace_file_reader &trace_reader)
438 status_t status = cStatusOK;
442 status = process_next_packet(trace_reader);
443 if ((status == cStatusNextFrame) || (status == cStatusResizeWindow) || (status == cStatusAtEOF) || (status == cStatusHardFailure))
450 //----------------------------------------------------------------------------------------------------------------------
451 // vogl_replayer::process_event
452 //----------------------------------------------------------------------------------------------------------------------
453 bool vogl_gl_replayer::update_window_dimensions()
457 m_pWindow->update_dimensions();
462 //----------------------------------------------------------------------------------------------------------------------
463 // vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap
464 //----------------------------------------------------------------------------------------------------------------------
465 bool vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap(const dynamic_string &filename)
467 m_dump_frontbuffer_filename = filename;
472 //----------------------------------------------------------------------------------------------------------------------
473 // vogl_gl_replayer::dump_frontbuffer_to_file
474 //----------------------------------------------------------------------------------------------------------------------
475 bool vogl_gl_replayer::dump_frontbuffer_to_file(const dynamic_string &filename)
477 if ((!m_is_valid) || (!m_pWindow))
483 uint width = 0, height = 0;
484 m_pWindow->get_actual_dimensions(width, height);
486 m_screenshot_buffer.resize(width * height * 3);
488 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_FRONT);
491 vogl_error_printf("%s: Failed calling glReadPixels() to take frontbuffer screenshot!\n", VOGL_METHOD_NAME);
496 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
498 success = file_utils::write_buf_to_file(filename.get_ptr(), pPNG_data, png_size);
501 vogl_error_printf("%s: Failed writing PNG screenshot to file \"%s\"\n", filename.get_ptr(), VOGL_METHOD_NAME);
505 vogl_message_printf("Wrote PNG screenshot to file \"%s\"\n", filename.get_ptr());
513 //----------------------------------------------------------------------------------------------------------------------
514 // vogl_replayer::trigger_pending_window_resize
515 //----------------------------------------------------------------------------------------------------------------------
516 vogl_gl_replayer::status_t vogl_gl_replayer::trigger_pending_window_resize(uint win_width, uint win_height)
520 m_pending_window_resize_width = win_width;
521 m_pending_window_resize_height = win_height;
522 m_pending_window_resize_attempt_counter = 0;
523 m_time_since_pending_window_resize.start();
525 m_pWindow->resize(win_width, win_height);
527 if (m_flags & cGLReplayerVerboseMode)
528 vogl_debug_printf("%s: Waiting for window to resize to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
530 return cStatusResizeWindow;
533 //----------------------------------------------------------------------------------------------------------------------
534 // vogl_replayer::clear_pending_window_resize
535 //----------------------------------------------------------------------------------------------------------------------
536 void vogl_gl_replayer::clear_pending_window_resize()
540 m_pending_window_resize_width = 0;
541 m_pending_window_resize_height = 0;
542 m_pending_window_resize_attempt_counter = 0;
545 //----------------------------------------------------------------------------------------------------------------------
546 // vogl_replayer::process_frame_check_for_pending_window_resize
547 //----------------------------------------------------------------------------------------------------------------------
548 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame_check_for_pending_window_resize()
552 const uint cMaxSecsToWait = 5;
554 if (!get_has_pending_window_resize())
557 if (m_pending_window_resize_attempt_counter >= cMaxSecsToWait)
559 vogl_warning_printf("Waited too long for window to resize to %ux%u, giving up and continuing replay\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
561 clear_pending_window_resize();
566 uint win_width = 0, win_height = 0;
567 m_pWindow->get_actual_dimensions(win_width, win_height);
569 if ((win_width != get_pending_window_resize_width()) ||
570 (win_height != get_pending_winow_resize_height()))
572 if (m_time_since_pending_window_resize.get_elapsed_secs() < 1.0f)
574 // sleep 1ms, then retry
576 return cStatusResizeWindow;
579 // What could possibly go wrong?
580 m_pending_window_resize_attempt_counter++;
581 if (m_pending_window_resize_attempt_counter < cMaxSecsToWait)
583 m_pWindow->resize(get_pending_window_resize_width(), get_pending_winow_resize_height());
585 m_time_since_pending_window_resize.start();
587 vogl_warning_printf("Waiting up to 5 secs for window to resize to %ux%u\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
588 return cStatusResizeWindow;
592 clear_pending_window_resize();
593 m_pWindow->update_dimensions();
598 //----------------------------------------------------------------------------------------------------------------------
599 // vogl_replayer::destroy_pending_snapshot
600 //----------------------------------------------------------------------------------------------------------------------
601 void vogl_gl_replayer::destroy_pending_snapshot()
605 if (m_pPending_snapshot)
607 if (m_delete_pending_snapshot_after_applying)
609 // Ensure the snapshot cache can't be pointing to the snapshot, just to be safe.
610 // TODO: Make this a real class damn it.
611 for (uint i = 0; i < m_snapshots.size(); i++)
613 if (m_snapshots[i].m_pSnapshot == m_pPending_snapshot)
615 m_snapshots.erase(i);
620 vogl_delete(const_cast<vogl_gl_state_snapshot *>(m_pPending_snapshot));
623 m_pPending_snapshot = NULL;
626 m_delete_pending_snapshot_after_applying = false;
629 //----------------------------------------------------------------------------------------------------------------------
630 // vogl_replayer::check_gl_error
631 // Returns *true* on error, just like vogl_check_gl_error()
632 //----------------------------------------------------------------------------------------------------------------------
633 bool vogl_gl_replayer::check_gl_error_internal(bool quietly, const char *pFile, uint line, const char *pFunc)
640 // http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
641 // "Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
642 GLenum gl_err = GL_ENTRYPOINT(glGetError)();
643 if (gl_err == GL_NO_ERROR)
648 process_entrypoint_warning("%s: GL error: 0x%08X (%u): %s (Called from File: %s Line: %u Func: %s)\n", VOGL_METHOD_NAME, gl_err, gl_err, g_gl_enums.find_name("ErrorCode", gl_err), pFile ? pFile : "?", line, pFunc ? pFunc : "?");
657 //----------------------------------------------------------------------------------------------------------------------
658 // vogl_replayer::clear_contexts
659 //----------------------------------------------------------------------------------------------------------------------
660 void vogl_gl_replayer::clear_contexts()
664 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
666 context_state *pContext_state = it->second;
668 vogl_delete(pContext_state);
673 m_cur_trace_context = 0;
674 m_cur_replay_context = NULL;
675 m_pCur_context_state = NULL;
678 //----------------------------------------------------------------------------------------------------------------------
679 // vogl_replayer::destroy_contexts
680 //----------------------------------------------------------------------------------------------------------------------
681 void vogl_gl_replayer::destroy_contexts()
685 if ((m_contexts.size()) && (m_pWindow->get_display()) && (GL_ENTRYPOINT(glXMakeCurrent)) && (GL_ENTRYPOINT(glXDestroyContext)))
687 GL_ENTRYPOINT(glXMakeCurrent)(m_pWindow->get_display(), (GLXDrawable)NULL, NULL);
689 vogl::vector<context_state *> contexts_to_destroy;
690 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
691 contexts_to_destroy.push_back(it->second);
693 // Delete "tail" contexts (ones that are not referenced by any other context) in sharegroups first.
694 while (contexts_to_destroy.size())
696 for (int i = 0; i < static_cast<int>(contexts_to_destroy.size()); i++)
698 context_state *pContext_state = contexts_to_destroy[i];
700 vogl_trace_ptr_value trace_context = pContext_state->m_context_desc.get_trace_context();
702 bool skip_context = false;
703 for (int j = 0; j < static_cast<int>(contexts_to_destroy.size()); j++)
708 if (contexts_to_destroy[j]->m_context_desc.get_trace_share_context() == trace_context)
718 // This context may have been the sharegroup's root and could have been already deleted.
719 if (!pContext_state->m_deleted)
721 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), pContext_state->m_replay_context);
724 contexts_to_destroy.erase(i);
733 //----------------------------------------------------------------------------------------------------------------------
734 // vogl_replayer::define_new_context
735 //----------------------------------------------------------------------------------------------------------------------
736 vogl_gl_replayer::context_state *vogl_gl_replayer::define_new_context(
737 vogl_trace_context_ptr_value trace_context, GLXContext replay_context, vogl_trace_context_ptr_value trace_share_context, GLboolean direct, gl_entrypoint_id_t creation_func, const int *pAttrib_list, uint attrib_list_size)
741 if ((!trace_context) || (!replay_context))
747 context_state *pContext_state = vogl_new(context_state, *this);
749 pContext_state->m_trace_context = trace_context;
750 pContext_state->m_replay_context = replay_context;
752 pContext_state->m_context_desc.init(creation_func, direct, trace_context, trace_share_context, vogl_context_attribs(pAttrib_list, attrib_list_size));
754 if (trace_share_context)
756 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
758 if (trace_share_context == it->first)
760 context_state *pShare_context = it->second;
761 while (!pShare_context->is_root_context())
762 pShare_context = pShare_context->m_pShared_state;
764 pContext_state->m_pShared_state = pShare_context;
765 pContext_state->m_pShared_state->m_ref_count++;
771 if (!pContext_state->m_pShared_state)
773 process_entrypoint_error("%s: Unable to find trace share context handle 0x%" PRIX64 "!\n", VOGL_METHOD_NAME, trace_share_context);
777 m_contexts.insert(trace_context, pContext_state);
779 return pContext_state;
782 //----------------------------------------------------------------------------------------------------------------------
783 // vogl_replayer::remap_context
784 //----------------------------------------------------------------------------------------------------------------------
785 GLXContext vogl_gl_replayer::remap_context(vogl_trace_context_ptr_value trace_context)
792 context_hash_map::iterator it = m_contexts.find(trace_context);
793 return (it == m_contexts.end()) ? NULL : it->second->m_replay_context;
796 //----------------------------------------------------------------------------------------------------------------------
797 // vogl_replayer::destroy_context
798 //----------------------------------------------------------------------------------------------------------------------
799 bool vogl_gl_replayer::destroy_context(vogl_trace_context_ptr_value trace_context)
803 VOGL_ASSERT(trace_context);
805 context_hash_map::iterator it = m_contexts.find(trace_context);
806 if (it == m_contexts.end())
809 context_state *pContext_state = it->second;
810 VOGL_ASSERT(pContext_state->m_ref_count >= 1);
811 VOGL_ASSERT(!pContext_state->m_deleted);
813 if (pContext_state->is_share_context())
815 VOGL_ASSERT(pContext_state->m_ref_count == 1);
817 context_state *pShare_context = pContext_state->m_pShared_state;
818 VOGL_ASSERT(pShare_context->m_ref_count >= 1);
820 pShare_context->m_ref_count--;
821 if (!pShare_context->m_ref_count)
823 VOGL_ASSERT(pShare_context->m_deleted);
825 vogl_trace_context_ptr_value trace_share_context = pShare_context->m_context_desc.get_trace_context();
827 vogl_delete(pShare_context);
829 bool removed = m_contexts.erase(trace_share_context);
830 VOGL_NOTE_UNUSED(removed);
831 VOGL_ASSERT(removed);
834 vogl_delete(pContext_state);
836 bool removed = m_contexts.erase(trace_context);
837 VOGL_NOTE_UNUSED(removed);
838 VOGL_ASSERT(removed);
842 pContext_state->m_deleted = true;
843 pContext_state->m_ref_count--;
845 if (!pContext_state->m_ref_count)
849 vogl_delete(pContext_state);
851 bool removed = m_contexts.erase(trace_context);
852 VOGL_NOTE_UNUSED(removed);
853 VOGL_ASSERT(removed);
860 //----------------------------------------------------------------------------------------------------------------------
861 // vogl_replayer::set_client_side_array_data
862 // glVertexPointer, glNormalPointer, etc. client side data
863 //----------------------------------------------------------------------------------------------------------------------
864 bool vogl_gl_replayer::set_client_side_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
868 // TODO: Add early out
869 GLint prev_client_active_texture = 0;
870 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
872 const uint tex_coords = math::minimum<uint>(m_pCur_context_state->m_context_info.is_core_profile() ? m_pCur_context_state->m_context_info.get_max_texture_units() : m_pCur_context_state->m_context_info.get_max_texture_coords(), VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS);
874 for (uint client_array_iter = 0; client_array_iter < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_array_iter++)
876 const vogl_client_side_array_desc_t &desc = g_vogl_client_side_array_descs[client_array_iter];
878 const bool is_texcoord_array = (client_array_iter == vogl_texcoord_pointer_array_id);
881 uint base_key_index = 0x1000 + client_array_iter;
883 // Special case texcoord pointers, which are accessed via the client active texture.
884 if (is_texcoord_array)
887 base_key_index = 0x2000;
890 for (uint inner_iter = 0; inner_iter < n; inner_iter++)
892 uint key_index = base_key_index + inner_iter;
894 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(key_index));
895 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
899 if (is_texcoord_array)
901 GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + inner_iter);
904 GLboolean is_enabled = GL_ENTRYPOINT(glIsEnabled)(desc.m_is_enabled);
909 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_binding, &binding);
914 GL_ENTRYPOINT(glGetPointerv)(desc.m_get_pointer, &ptr);
918 uint8_vec &array_data = is_texcoord_array ? m_client_side_texcoord_data[inner_iter] : m_client_side_array_data[client_array_iter];
919 if (ptr != array_data.get_ptr())
925 GLint type = GL_BOOL;
928 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_type, &type);
932 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_stride, &stride);
937 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_size, &size);
940 uint type_size = vogl_get_gl_type_size(type);
943 process_entrypoint_error("%s: Can't determine type size of enabled client side array set by func %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
947 if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointerEXT) ||
948 (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointerEXT) ||
949 (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointerEXT))
953 else if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointerEXT))
957 else if ((size < 1) && (size > 4))
959 process_entrypoint_error("%s: Size of client side array set by func %s must be between 1 and 4\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
964 stride = type_size * size;
966 uint first_vertex_ofs = (start + basevertex) * stride;
967 uint last_vertex_ofs = (end + basevertex) * stride;
968 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
969 uint total_data_size = last_vertex_ofs + stride;
974 process_entrypoint_error("%s: Failed finding client side vertex data blob set by func %s \n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
980 if (vertex_data_size != pVertex_blob->size())
982 process_entrypoint_error("%s: %s will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, vertex_data_size, pVertex_blob->size());
983 temp_blob = *pVertex_blob;
984 temp_blob.resize(vertex_data_size);
985 pVertex_blob = &temp_blob;
988 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
989 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
990 if (bytes_to_copy != pVertex_blob->size())
992 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
993 process_entrypoint_error("%s: %s accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, first_vertex_ofs + total_data_size);
996 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= array_data.size());
998 memcpy(array_data.get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1002 GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
1007 //----------------------------------------------------------------------------------------------------------------------
1008 // vogl_replayer::set_client_side_vertex_attrib_array_data
1009 // glVertexAttrib client side data
1010 //----------------------------------------------------------------------------------------------------------------------
1011 bool vogl_gl_replayer::set_client_side_vertex_attrib_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
1015 // TODO: Add early out
1017 for (int vertex_attrib_index = 0; vertex_attrib_index < static_cast<int>(m_pCur_context_state->m_context_info.get_max_vertex_attribs()); vertex_attrib_index++)
1019 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(vertex_attrib_index));
1021 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
1026 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1031 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &cur_buf);
1035 GLvoid *attrib_ptr = NULL;
1036 GL_ENTRYPOINT(glGetVertexAttribPointerv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib_ptr);
1040 if (attrib_ptr != m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr())
1046 GLint attrib_size = 0;
1047 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib_size);
1049 GLint attrib_type = 0;
1050 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib_type);
1052 GLint attrib_stride = 0;
1053 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib_stride);
1058 process_entrypoint_error("%s: Failed finding client side vertex data blob for generic vertex attrib %u\n", VOGL_METHOD_NAME, vertex_attrib_index);
1064 if ((attrib_size != GL_BGRA) && (attrib_size < 1) && (attrib_size > 4))
1066 process_entrypoint_error("%s: Enabled vertex attribute index %i has invalid size 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_size);
1069 if ((attrib_size >= 1) && (attrib_size <= 4))
1070 num_comps = attrib_size;
1072 uint type_size = vogl_get_gl_type_size(attrib_type);
1075 process_entrypoint_error("%s: Vertex attribute index %i has unsupported type 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_type);
1079 uint stride = attrib_stride ? attrib_stride : (type_size * num_comps);
1081 uint first_vertex_ofs = (start + basevertex) * stride;
1082 uint last_vertex_ofs = (end + basevertex) * stride;
1083 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
1084 uint total_data_size = last_vertex_ofs + stride;
1086 uint8_vec temp_blob;
1087 if (vertex_data_size != pVertex_blob->size())
1089 process_entrypoint_error("%s: Vertex attribute index %i will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, vertex_attrib_index, vertex_data_size, pVertex_blob->size());
1090 temp_blob = *pVertex_blob;
1091 temp_blob.resize(vertex_data_size);
1092 pVertex_blob = &temp_blob;
1095 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
1096 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
1097 if (bytes_to_copy != pVertex_blob->size())
1099 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
1100 process_entrypoint_error("%s: Vertex attribute index %i accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, vertex_attrib_index, first_vertex_ofs + total_data_size);
1103 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= m_client_side_vertex_attrib_data[vertex_attrib_index].size());
1105 memcpy(m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1111 //----------------------------------------------------------------------------------------------------------------------
1112 // vogl_replayer::draw_elements_client_side_array_setup
1113 //----------------------------------------------------------------------------------------------------------------------
1114 bool vogl_gl_replayer::draw_elements_client_side_array_setup(
1120 vogl_trace_ptr_value trace_indices_ptr_value, const GLvoid *&pIndices,
1122 bool has_valid_start_end,
1127 VOGL_NOTE_UNUSED(mode);
1131 GLuint element_array_buffer = 0;
1132 uint index_size = 0;
1135 index_size = vogl_get_gl_type_size(type);
1138 process_entrypoint_error("%s: Invalid type parameter 0x%08X\n", VOGL_METHOD_NAME, type);
1142 element_array_buffer = vogl_get_bound_gl_buffer(GL_ELEMENT_ARRAY_BUFFER);
1143 if (element_array_buffer)
1145 // trace_indices_ptr_value is actually an offset into the buffer, not a real trace ptr
1146 pIndices = reinterpret_cast<GLvoid *>(trace_indices_ptr_value);
1152 process_entrypoint_warning("%s: count parameter is <= 0 (%i)\n", VOGL_METHOD_NAME, count);
1156 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
1159 if ((indexed) && (!element_array_buffer) && (trace_indices_ptr_value))
1161 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob. Can't remap indices pointer!\n", VOGL_METHOD_NAME);
1162 if (trace_indices_ptr_value)
1164 // We can't remap the pointer to valid memory, so give up.
1169 // TODO: Check for client side array usage but no data in blob (which would be a desync or error)
1173 // TODO: If a VAO is bound, client side data isn't supported according to this:
1174 // http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
1176 //GLint current_vertex_array_binding = 0;
1177 //ACTUAL_GL_ENTRYPOINT(glGetIntegerv)(GL_VERTEX_ARRAY_BINDING, ¤t_vertex_array_binding);
1179 if ((indexed) && (!element_array_buffer))
1181 const uint8_vec *pIndices_vec = map.get_blob(string_hash("indices"));
1184 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob\n", VOGL_METHOD_NAME);
1188 pIndices = pIndices_vec->get_ptr();
1191 process_entrypoint_error("%s: No element array buffer is bound, but key value map has an empty indices blob\n", VOGL_METHOD_NAME);
1195 if ((pIndices_vec->size() / index_size) != static_cast<uint>(count))
1197 process_entrypoint_error("%s: Client side index data blob stored in packet is too small (wanted %u indices, got %u indices)\n", VOGL_METHOD_NAME, count, pIndices_vec->size() / index_size);
1202 if ((indexed) && (!has_valid_start_end))
1204 uint total_index_data_size = count * index_size;
1206 const uint8 *pIndices_to_scan = static_cast<const uint8 *>(pIndices);
1208 if (element_array_buffer)
1210 if (m_index_data.size() < total_index_data_size)
1211 m_index_data.resize(total_index_data_size);
1213 pIndices_to_scan = m_index_data.get_ptr();
1217 GL_ENTRYPOINT(glGetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)pIndices, total_index_data_size, m_index_data.get_ptr());
1219 if (check_gl_error())
1221 process_entrypoint_warning("%s: GL error while trying to retrieve index buffer data\n", VOGL_METHOD_NAME);
1223 memset(m_index_data.get_ptr(), 0, total_index_data_size);
1227 start = cUINT32_MAX;
1230 for (int i = 0; i < count; i++)
1234 if (type == GL_UNSIGNED_BYTE)
1235 v = pIndices_to_scan[i];
1236 else if (type == GL_UNSIGNED_SHORT)
1237 v = reinterpret_cast<const uint16 *>(pIndices_to_scan)[i];
1238 else if (type == GL_UNSIGNED_INT)
1239 v = reinterpret_cast<const uint32 *>(pIndices_to_scan)[i];
1242 process_entrypoint_error("%s: Invalid index type\n", VOGL_METHOD_NAME);
1246 start = math::minimum(start, v);
1247 end = math::maximum(end, v);
1250 has_valid_start_end = true;
1253 if (!set_client_side_array_data(map, start, end, basevertex))
1256 if (!set_client_side_vertex_attrib_array_data(map, start, end, basevertex))
1262 //----------------------------------------------------------------------------------------------------------------------
1263 // vogl_replayer::determine_uniform_replay_location
1264 //----------------------------------------------------------------------------------------------------------------------
1265 GLint vogl_gl_replayer::determine_uniform_replay_location(GLuint trace_program, GLint trace_location)
1269 GLint replay_location = trace_location;
1271 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1272 if (it == get_shared_state()->m_glsl_program_hash_map.end())
1274 process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1278 glsl_program_state &state = it->second;
1280 uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1281 if (loc_it == state.m_uniform_locations.end())
1283 process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1287 replay_location = loc_it->second;
1290 return replay_location;
1293 //----------------------------------------------------------------------------------------------------------------------
1294 // vogl_replayer::process_entrypoint_print_summary_context
1295 //----------------------------------------------------------------------------------------------------------------------
1296 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1300 if (!m_pCur_gl_packet)
1303 console::printf(msg_type, "While processing GL entrypoint packet func %s, frame %u, swaps %u, GL call counter %" PRIu64 ", packet start trace context 0x%" PRIX64 ", cur trace context 0x%" PRIX64 ", trace thread 0x%" PRIX64 ":\n",
1304 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1305 m_frame_index, m_total_swaps,
1306 m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1307 m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1308 m_cur_trace_context,
1309 m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1312 dynamic_string_array backtrace;
1313 if (get_printable_backtrace(backtrace))
1315 console::printf("Backtrace:\n");
1316 for (uint i = 0; i < backtrace.size(); i++)
1317 console::printf("%s\n", backtrace[i].get_ptr());
1322 //----------------------------------------------------------------------------------------------------------------------
1323 // vogl_replayer::print_detailed_context
1324 //----------------------------------------------------------------------------------------------------------------------
1325 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1331 vogl_loose_file_blob_manager blob_file_manager;
1332 blob_file_manager.init(cBMFWritable);
1334 vogl_trace_packet::json_serialize_params serialize_params;
1335 serialize_params.m_output_basename = "replay_error";
1336 serialize_params.m_cur_frame = m_frame_index;
1337 serialize_params.m_blob_file_size_threshold = 1024;
1338 serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1339 m_pCur_gl_packet->json_serialize(node, serialize_params);
1341 dynamic_string node_str;
1342 node.serialize(node_str, true, 0);
1343 console::printf(msg_type, "Packet at call counter %" PRIu64 " as JSON:\n%s\n", m_pCur_gl_packet->get_entrypoint_packet().m_call_counter, node_str.get_ptr());
1346 //----------------------------------------------------------------------------------------------------------------------
1347 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1348 //----------------------------------------------------------------------------------------------------------------------
1349 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1353 if (!m_pCur_gl_packet)
1356 dump_packet_as_func_call(*m_pCur_gl_packet);
1358 if (!(m_flags & cGLReplayerDumpPacketsOnError))
1361 print_detailed_context(msg_type);
1364 //----------------------------------------------------------------------------------------------------------------------
1365 // vogl_replayer::process_entrypoint_info
1366 //----------------------------------------------------------------------------------------------------------------------
1367 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1371 process_entrypoint_print_summary_context(cInfoConsoleMessage);
1374 va_start(args, pFmt);
1375 console::vprintf(cInfoConsoleMessage, pFmt, args);
1378 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1381 //----------------------------------------------------------------------------------------------------------------------
1382 // vogl_replayer::process_entrypoint_message
1383 //----------------------------------------------------------------------------------------------------------------------
1384 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1388 process_entrypoint_print_summary_context(cMessageConsoleMessage);
1391 va_start(args, pFmt);
1392 console::vprintf(cMessageConsoleMessage, pFmt, args);
1395 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1398 //----------------------------------------------------------------------------------------------------------------------
1399 // vogl_replayer::process_entrypoint_warning
1400 //----------------------------------------------------------------------------------------------------------------------
1401 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1405 process_entrypoint_print_summary_context(cWarningConsoleMessage);
1408 va_start(args, pFmt);
1409 console::vprintf(cWarningConsoleMessage, pFmt, args);
1412 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1415 //----------------------------------------------------------------------------------------------------------------------
1416 // vogl_replayer::process_entrypoint_error
1417 //----------------------------------------------------------------------------------------------------------------------
1418 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1422 process_entrypoint_print_summary_context(cErrorConsoleMessage);
1425 va_start(args, pFmt);
1426 console::vprintf(cErrorConsoleMessage, pFmt, args);
1429 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1432 //----------------------------------------------------------------------------------------------------------------------
1433 // vogl_replayer::switch_contexts
1434 //----------------------------------------------------------------------------------------------------------------------
1435 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1440 //if (m_pCur_gl_packet->get_call_counter() == 25583)
1441 // vogl_debug_break();
1443 //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1444 if (trace_context == m_cur_trace_context)
1447 if (m_flags & cGLReplayerDebugMode)
1449 process_entrypoint_message("%s: Forcing context switch via glXMakeCurrent, from current trace context 0x%" PRIX64 " to new context 0x%" PRIX64 "\n", VOGL_METHOD_NAME, cast_val_to_uint64(m_cur_trace_context), cast_val_to_uint64(trace_context));
1452 // pContext_state will be NULL if they are unmapping!
1453 context_state *pContext_state = get_trace_context_state(trace_context);
1454 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1456 const Display *dpy = m_pWindow->get_display();
1457 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1459 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1462 process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1463 return cStatusHardFailure;
1466 m_cur_trace_context = trace_context;
1467 m_cur_replay_context = replay_context;
1468 m_pCur_context_state = pContext_state;
1473 //----------------------------------------------------------------------------------------------------------------------
1474 // vogl_replayer::debug_callback_arb
1475 //----------------------------------------------------------------------------------------------------------------------
1476 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1480 VOGL_NOTE_UNUSED(length);
1482 char final_message[4096];
1484 context_state *pContext_state = (context_state *)(pUser_param);
1486 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1490 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1491 cast_val_to_uint64(pContext_state->m_trace_context), cast_val_to_uint64(pContext_state->m_replay_context), cast_val_to_uint64(pContext_state->m_last_call_counter), final_message);
1495 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1499 //----------------------------------------------------------------------------------------------------------------------
1500 // vogl_replayer::is_extension_supported
1501 //----------------------------------------------------------------------------------------------------------------------
1502 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1506 if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1508 return m_pCur_context_state->m_context_info.supports_extension(pExt);
1516 //----------------------------------------------------------------------------------------------------------------------
1517 // vogl_replayer::context_state::handle_context_made_current
1518 //----------------------------------------------------------------------------------------------------------------------
1519 bool vogl_gl_replayer::context_state::handle_context_made_current()
1523 if (m_has_been_made_current)
1526 VOGL_CHECK_GL_ERROR;
1528 m_has_been_made_current = true;
1530 if (!m_context_info.init(m_context_desc))
1532 vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1536 if (!m_context_info.get_max_vertex_attribs())
1538 vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1540 else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1542 vogl_error_printf("%s: GL_MAX_VERTEX_ATTRIBS is too large, max supported is %u. Please increase VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES.\n", VOGL_METHOD_NAME, VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES);
1546 if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1548 vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1551 // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1552 // TODO: All more object types
1553 vogl::vector<GLuint> dummy_handles(65536);
1555 GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1556 GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1557 GL_ENTRYPOINT(glGenLists)(8000);
1558 GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1560 GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1561 GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1562 GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1563 GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1564 GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1566 for (uint i = 0; i < 22000; i++)
1567 GL_ENTRYPOINT(glCreateProgram)();
1569 vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1572 VOGL_CHECK_GL_ERROR;
1577 //----------------------------------------------------------------------------------------------------------------------
1578 // vogl_replayer::handle_context_made_current
1579 //----------------------------------------------------------------------------------------------------------------------
1580 bool vogl_gl_replayer::handle_context_made_current()
1584 if (!m_pCur_context_state->handle_context_made_current())
1587 if ((m_pCur_context_state->m_context_info.is_debug_context()) && (GL_ENTRYPOINT(glDebugMessageCallbackARB)) && (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_debug_output")))
1589 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1590 GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1594 if (m_flags & cGLReplayerVerboseMode)
1596 vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1598 (uint64_t)m_cur_trace_context,
1599 (uint64_t)m_cur_replay_context,
1600 m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1606 //----------------------------------------------------------------------------------------------------------------------
1607 // vogl_replayer::dump_context_attrib_list
1608 //----------------------------------------------------------------------------------------------------------------------
1609 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1615 vogl_debug_printf("Attrib list is NULL\n");
1618 vogl_debug_printf("Context attribs:\n");
1625 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1629 uint key = pAttrib_list[ofs];
1636 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1640 uint value = pAttrib_list[ofs];
1643 vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1645 vogl_debug_printf("End of context attribs\n");
1648 //----------------------------------------------------------------------------------------------------------------------
1649 // vogl_replayer::find_attrib_key
1650 //----------------------------------------------------------------------------------------------------------------------
1651 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1656 while (ofs < attrib_list.size())
1658 int key = attrib_list[ofs];
1662 if (++ofs >= attrib_list.size())
1664 process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1668 if (key == key_to_find)
1676 //----------------------------------------------------------------------------------------------------------------------
1677 // vogl_replayer::create_context_attribs
1678 //----------------------------------------------------------------------------------------------------------------------
1679 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1680 vogl_trace_context_ptr_value trace_context, Display *dpy, GLXFBConfig config, vogl_trace_context_ptr_value trace_share_context, GLXContext replay_share_context, Bool direct,
1681 const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1685 vogl::vector<int> temp_attrib_list;
1687 if ((pTrace_attrib_list) && (trace_attrib_list_size))
1689 temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1690 if (temp_attrib_list.back() != 0)
1692 process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1697 if (expecting_attribs)
1699 if (m_flags & cGLReplayerVerboseMode)
1700 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1703 temp_attrib_list.push_back(0);
1706 if (m_flags & cGLReplayerForceDebugContexts)
1708 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1709 int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1710 if (context_flags_ofs < 0)
1712 temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1713 temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1714 temp_attrib_list.push_back(0);
1716 if (m_flags & cGLReplayerVerboseMode)
1717 process_entrypoint_warning("%s: Appending GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB to attrib list to enable debug context\n", VOGL_METHOD_NAME);
1721 temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1723 if (m_flags & cGLReplayerVerboseMode)
1724 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1727 int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1728 int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1730 bool slammed_up_to_3_0 = false;
1731 if (context_major_version_ofs < 0)
1733 // Don't slam up if they haven't requested a specific GL version, the driver will give us the most recent version that is backwards compatible with 1.0 (i.e. 4.3 for NVidia's current dirver).
1735 temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1736 temp_attrib_list.push_back(3);
1737 temp_attrib_list.push_back(0);
1739 slammed_up_to_3_0 = true;
1742 else if (temp_attrib_list[context_major_version_ofs] < 3)
1744 temp_attrib_list[context_major_version_ofs] = 3;
1746 slammed_up_to_3_0 = true;
1749 if (slammed_up_to_3_0)
1751 if (context_minor_version_ofs < 0)
1753 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1754 temp_attrib_list.push_back(0);
1755 temp_attrib_list.push_back(0);
1759 temp_attrib_list[context_minor_version_ofs] = 0;
1762 process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1766 const int *pAttrib_list = temp_attrib_list.get_ptr();
1767 const uint attrib_list_size = temp_attrib_list.size();
1769 if (m_flags & cGLReplayerVerboseMode)
1770 dump_context_attrib_list(pAttrib_list, attrib_list_size);
1772 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1773 if (!replay_context)
1777 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1778 return cStatusHardFailure;
1782 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1790 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1791 VOGL_NOTE_UNUSED(pContext_state);
1795 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1802 //----------------------------------------------------------------------------------------------------------------------
1803 // vogl_replayer::process_pending_make_current
1804 //----------------------------------------------------------------------------------------------------------------------
1805 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1809 if (!m_pending_make_current_packet.is_valid())
1812 vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1814 Bool trace_result = gl_packet.get_return_value<Bool>();
1816 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1817 VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1819 // pContext_state will be NULL if they are unmapping!
1820 vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1821 context_state *pContext_state = get_trace_context_state(trace_context);
1822 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1824 if ((trace_context) && (!replay_context))
1826 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1827 m_pending_make_current_packet.clear();
1828 return cStatusHardFailure;
1831 const Display *dpy = m_pWindow->get_display();
1832 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1834 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1839 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1840 m_pending_make_current_packet.clear();
1841 return cStatusHardFailure;
1845 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1850 m_cur_trace_context = trace_context;
1851 m_cur_replay_context = replay_context;
1852 m_pCur_context_state = pContext_state;
1856 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1859 if (m_cur_replay_context)
1861 int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1862 int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1863 int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1864 int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1865 int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1866 int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1868 if (!m_pCur_context_state->m_has_been_made_current)
1870 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1871 viewport_x, viewport_y,
1872 viewport_width, viewport_height,
1873 win_width, win_height);
1876 GLint cur_viewport[4];
1877 GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1879 uint cur_win_width = 0, cur_win_height = 0;
1880 m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1882 if (!m_pCur_context_state->m_has_been_made_current)
1884 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1885 cur_viewport[0], cur_viewport[1],
1886 cur_viewport[2], cur_viewport[3],
1887 cur_win_width, cur_win_height);
1890 if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1892 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1895 if (!handle_context_made_current())
1896 return cStatusHardFailure;
1900 m_last_processed_call_counter = gl_packet.get_call_counter();
1902 m_pending_make_current_packet.clear();
1907 //----------------------------------------------------------------------------------------------------------------------
1908 // vogl_process_internal_trace_command_ctypes_packet
1909 //----------------------------------------------------------------------------------------------------------------------
1910 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1914 // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1915 int num_trace_ctypes = kvm.get_int("num_ctypes");
1916 VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1918 // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1919 // This will need to be revisited once we port to other OS's.
1920 // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1921 for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1923 const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1925 uint base_index = ctype_iter << 8;
1926 dynamic_string name(kvm.get_string(base_index++));
1927 dynamic_string ctype(kvm.get_string(base_index++));
1928 int size = kvm.get_int(base_index++);
1929 uint loki_type_flags = kvm.get_uint(base_index++);
1930 bool is_pointer = kvm.get_bool(base_index++);
1931 bool is_opaque_pointer = kvm.get_bool(base_index++);
1932 bool is_pointer_diff = kvm.get_bool(base_index++);
1933 bool is_opaque_type = kvm.get_bool(base_index++);
1935 VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1936 VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1937 if (!desc.m_is_opaque_type)
1939 VOGL_VERIFY(size == desc.m_size);
1942 const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1943 VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1945 VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1946 VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1947 VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1948 VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1954 //----------------------------------------------------------------------------------------------------------------------
1955 // vogl_replayer::process_internal_trace_command
1956 //----------------------------------------------------------------------------------------------------------------------
1957 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1961 VOGL_NOTE_UNUSED(gl_packet);
1963 GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1964 GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1965 VOGL_NOTE_UNUSED(size);
1966 vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1967 VOGL_NOTE_UNUSED(trace_data_ptr_value);
1969 vogl_gl_replayer::status_t status = cStatusOK;
1973 case cITCRDemarcation:
1977 case cITCRKeyValueMap:
1979 const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
1981 dynamic_string cmd_type(kvm.get_string("command_type"));
1982 if (cmd_type == "state_snapshot")
1984 dynamic_string text_id(kvm.get_string("id"));
1985 dynamic_string binary_id(kvm.get_string("binary_id"));
1986 if (text_id.is_empty() && binary_id.is_empty())
1988 process_entrypoint_error("%s: Missing id and binary_id fields in glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
1989 return cStatusHardFailure;
1992 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
1994 // TODO: Make a 1st class snapshot cache class
1995 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
1996 vogl_gl_state_snapshot *pSnapshot = NULL;
1997 if (m_flags & cGLReplayerSnapshotCaching)
1999 for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2001 if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2003 pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2006 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2007 m_snapshots.erase(snapshot_index);
2008 m_snapshots.insert(0, cache_entry);
2017 timed_scope ts("Deserialize snapshot time");
2019 if (!m_pBlob_manager)
2021 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2022 return cStatusHardFailure;
2025 uint8_vec snapshot_data;
2027 if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2029 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2030 return cStatusHardFailure;
2033 vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2038 if (id_to_use == text_id)
2039 success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2041 success = doc.binary_deserialize(snapshot_data);
2042 if (!success || (!doc.get_root()))
2044 process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2045 return cStatusHardFailure;
2048 pSnapshot = vogl_new(vogl_gl_state_snapshot);
2049 if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2051 vogl_delete(pSnapshot);
2054 process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2055 return cStatusHardFailure;
2058 if (m_flags & cGLReplayerSnapshotCaching)
2060 snapshot_cache_entry new_cache_entry;
2061 new_cache_entry.m_name = id_to_use;
2062 new_cache_entry.m_pSnapshot = pSnapshot;
2063 m_snapshots.insert(0, new_cache_entry);
2065 // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2066 while (m_snapshots.size() > 3)
2068 vogl_delete(m_snapshots.back().m_pSnapshot);
2069 m_snapshots.resize(m_snapshots.size() - 1);
2074 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2076 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2078 if (m_flags & cGLReplayerSnapshotCaching)
2080 VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2082 vogl_delete(m_snapshots[0].m_pSnapshot);
2083 m_snapshots.erase(0U);
2086 if (m_flags & cGLReplayerSnapshotCaching)
2088 vogl_delete(pSnapshot);
2092 process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2096 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2098 else if (cmd_type == "ctypes")
2100 m_ctypes_packet = *m_pCur_gl_packet;
2102 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2103 return cStatusHardFailure;
2105 else if (cmd_type == "entrypoints")
2111 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2117 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2125 //----------------------------------------------------------------------------------------------------------------------
2126 // vogl_replayer::check_program_binding_shadow
2127 //----------------------------------------------------------------------------------------------------------------------
2128 bool vogl_gl_replayer::check_program_binding_shadow()
2132 if (!m_pCur_context_state)
2135 // Make sure shadow is good
2136 GLint actual_current_replay_program = 0;
2137 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2140 if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2143 // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2144 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2145 if ((!check_gl_error()) && (is_still_program))
2147 GLint marked_for_deletion = GL_FALSE;
2148 GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2150 if ((!check_gl_error()) && (marked_for_deletion))
2158 //----------------------------------------------------------------------------------------------------------------------
2159 // vogl_replayer::handle_use_program
2160 //----------------------------------------------------------------------------------------------------------------------
2161 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2165 // TODO: This code assumes the non-ARB entrypoints are being used, which works fine on NV but who knows what'll happen on other drivers.
2166 check_program_binding_shadow();
2168 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2169 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2170 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2172 // For safety, absorb any previous error.
2175 GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2176 GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2178 bool prev_is_program = false;
2179 GLint prev_link_status = false;
2180 GLint prev_is_marked_for_deletion = false;
2181 vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2183 if ((prev_replay_program) && (replay_handle != prev_replay_program))
2185 prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2186 check_gl_error_quietly();
2188 if (prev_is_program)
2190 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2191 check_gl_error_quietly();
2193 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2194 check_gl_error_quietly();
2196 if (prev_is_marked_for_deletion)
2198 // The currently bound program is marked for deletion, so record which shaders are attached to it in case the program is actually deleted by the driver on the UseProgram() call.
2199 GLint num_attached_shaders = 0;
2200 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2201 check_gl_error_quietly();
2203 if (num_attached_shaders)
2205 prev_attached_replay_shaders.resize(num_attached_shaders);
2207 GLsizei actual_count = 0;
2208 GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2209 check_gl_error_quietly();
2211 VOGL_ASSERT(actual_count == num_attached_shaders);
2217 if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2218 GL_ENTRYPOINT(glUseProgram)(replay_handle);
2220 GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2222 // Can't shadow if glUseProgram failed.
2223 if (check_gl_error())
2226 if ((prev_replay_program) && (prev_replay_program != replay_handle))
2228 bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2229 if (!is_prev_still_program)
2231 VOGL_ASSERT(prev_is_program);
2232 VOGL_ASSERT(prev_is_marked_for_deletion);
2234 // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2235 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2236 VOGL_ASSERT(was_deleted);
2237 VOGL_NOTE_UNUSED(was_deleted);
2239 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2240 VOGL_ASSERT(was_deleted);
2242 was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2243 if ((prev_link_status) && (!was_deleted))
2248 for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2250 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2252 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2253 check_gl_error_quietly();
2255 if (is_still_shader)
2258 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2260 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2264 // The attached shader is now really dead.
2265 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2266 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2268 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, prev_trace_program, prev_replay_program);
2274 m_pCur_context_state->m_cur_replay_program = replay_handle;
2275 m_pCur_context_state->m_cur_trace_program = trace_handle;
2278 //----------------------------------------------------------------------------------------------------------------------
2279 // vogl_replayer::handle_delete_program
2280 //----------------------------------------------------------------------------------------------------------------------
2281 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2285 check_program_binding_shadow();
2287 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2289 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2290 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2291 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2293 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2294 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2296 if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2299 context_state *pContext = it->second;
2300 if (pContext->m_pShared_state == pContext_shareroot)
2302 if (pContext->m_cur_trace_program == trace_handle)
2304 process_entrypoint_error("%s: Trace program %u replay program %u is being deleted on context 0x%" PRIx64 ", but it's currently bound to trace context 0x%" PRIx64 "! This scenario is not currently supported with sharelists.\n",
2305 VOGL_METHOD_NAME, trace_handle, replay_handle,
2306 cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2307 cast_val_to_uint64(it->first));
2312 bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2313 check_gl_error_quietly();
2315 vogl::growable_array<GLuint, 8> attached_replay_shaders;
2317 if ((is_program) && (replay_handle))
2319 GLint num_attached_shaders = 0;
2320 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2321 check_gl_error_quietly();
2323 if (num_attached_shaders)
2325 attached_replay_shaders.resize(num_attached_shaders);
2327 GLsizei actual_count = 0;
2328 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2329 check_gl_error_quietly();
2331 VOGL_ASSERT(actual_count == num_attached_shaders);
2335 GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2337 bool deletion_succeeded = !check_gl_error();
2338 if (!deletion_succeeded)
2340 VOGL_ASSERT(!is_program);
2342 process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2349 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2350 check_gl_error_quietly();
2352 GLint marked_for_deletion = 0;
2353 if (is_still_program)
2355 // It must still be bound to the context, or referred to in some other way that we don't know about.
2356 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2357 bool delete_status_check_succeeded = !check_gl_error_quietly();
2359 VOGL_VERIFY(delete_status_check_succeeded);
2360 VOGL_VERIFY(marked_for_deletion);
2362 else if (!is_still_program)
2364 VOGL_ASSERT(is_program);
2366 // The program is really gone now.
2367 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2368 VOGL_ASSERT(was_deleted);
2369 VOGL_NOTE_UNUSED(was_deleted);
2371 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2372 VOGL_ASSERT(was_deleted);
2374 get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2376 if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2378 // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2380 m_pCur_context_state->m_cur_replay_program = 0;
2381 m_pCur_context_state->m_cur_trace_program = 0;
2384 for (uint i = 0; i < attached_replay_shaders.size(); i++)
2386 GLuint replay_shader_handle = attached_replay_shaders[i];
2388 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2389 check_gl_error_quietly();
2391 if (is_still_shader)
2394 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2396 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2400 // The attached shader is now really dead.
2401 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2402 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2404 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, trace_handle, replay_handle);
2410 //----------------------------------------------------------------------------------------------------------------------
2411 // vogl_replayer::handle_delete_shader
2412 //----------------------------------------------------------------------------------------------------------------------
2413 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2417 check_program_binding_shadow();
2421 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2423 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2424 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2425 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2427 GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2429 bool deletion_succeeded = !check_gl_error();
2430 if (!deletion_succeeded)
2432 process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2439 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2440 check_gl_error_quietly();
2442 if (!is_still_shader)
2444 // The shader is really gone.
2445 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2446 VOGL_ASSERT(was_deleted);
2447 VOGL_NOTE_UNUSED(was_deleted);
2451 GLint marked_for_deletion = 0;
2452 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2453 check_gl_error_quietly();
2455 VOGL_VERIFY(marked_for_deletion);
2457 // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2458 // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2462 //----------------------------------------------------------------------------------------------------------------------
2463 // vogl_replayer::handle_detach_shader
2464 //----------------------------------------------------------------------------------------------------------------------
2465 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2467 GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2468 GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2470 GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2471 GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2475 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2477 GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2478 check_gl_error_quietly();
2480 GLint marked_for_deletion = 0;
2481 GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2482 check_gl_error_quietly();
2484 if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2485 GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2488 VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2489 GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2492 bool detach_failed = check_gl_error();
2494 GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2495 check_gl_error_quietly();
2499 if ((marked_for_deletion) && (was_shader) && (!is_shader))
2501 // The shader is really gone now.
2502 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2503 VOGL_ASSERT(was_deleted);
2504 VOGL_NOTE_UNUSED(was_deleted);
2509 //----------------------------------------------------------------------------------------------------------------------
2510 // vogl_gl_replayer::handle_link_program
2511 //----------------------------------------------------------------------------------------------------------------------
2512 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2516 GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2517 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2519 GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2523 process_entrypoint_warning("%s: Handle is not a program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2526 const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2530 process_entrypoint_warning("%s: JSON metadata document is missing, program will be linked without setting its attributes or initializing the uniform location shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2532 else if ((pDoc) && (!pDoc->is_object()))
2534 process_entrypoint_warning("%s: JSON metadata document must be an object, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2538 int trace_active_attributes = 0;
2539 int trace_active_uniforms = 0;
2540 int trace_active_uniform_blocks = 0;
2541 int trace_link_status = 1;
2543 VOGL_NOTE_UNUSED(trace_active_uniforms);
2544 VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2548 const json_node &doc_root = *pDoc->get_root();
2550 trace_link_status = doc_root.value_as_int("link_status");
2551 trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2552 trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2553 trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2555 const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2558 for (uint i = 0; i < pAttrib_node->size(); i++)
2560 const json_node *pAttrib = pAttrib_node->get_child(i);
2567 const char *pName = pAttrib->value_as_string_ptr("name");
2568 int attrib_loc = pAttrib->value_as_int("location", -1);
2570 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2572 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2573 GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2575 GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2582 const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2583 if (pOutputs_object)
2585 for (uint i = 0; i < pOutputs_object->size(); i++)
2587 const json_node *pOutput_node = pOutputs_object->get_child(i);
2591 dynamic_string name(pOutput_node->value_as_string("name"));
2592 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2595 int location = pOutput_node->value_as_int("location");
2596 int location_index = pOutput_node->value_as_int("location_index");
2598 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2600 GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2605 process_entrypoint_error("%s: GL_ARB_blend_func_extended is not supported, but trace program %u GL program %u uses a non-zero location index\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2607 GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2614 GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2615 GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2618 const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2619 if (pTransform_feedback_varyings)
2621 dynamic_string_array names;
2623 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2625 const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2629 GLint index = pVarying_node->value_as_int("index");
2633 dynamic_string name(pVarying_node->value_as_string("name"));
2635 //GLsizei size(pVarying_node->value_as_int("size"));
2636 //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2638 names.ensure_element_is_valid(index);
2639 names[index] = name;
2642 vogl::vector<GLchar *> varyings(names.size());
2643 for (uint i = 0; i < names.size(); i++)
2644 varyings[i] = (GLchar *)(names[i].get_ptr());
2646 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2652 switch (entrypoint_id)
2654 case VOGL_ENTRYPOINT_glLinkProgram:
2656 GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2659 case VOGL_ENTRYPOINT_glLinkProgramARB:
2661 GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2664 case VOGL_ENTRYPOINT_glProgramBinary:
2666 GL_ENTRYPOINT(glProgramBinary)(replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2678 GLint replay_link_status = 0;
2679 GLint replay_active_attributes = 0;
2680 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2682 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2685 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2690 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2693 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2697 if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2700 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2701 success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2703 success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle);
2706 process_entrypoint_warning("%s: Failed inserting into link time program shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2709 if ((pDoc) && (replay_link_status != trace_link_status))
2711 process_entrypoint_warning("%s: Trace link status (%i) differs from replay link status (%i), trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_link_status, replay_link_status, trace_handle, replay_handle);
2714 if (!replay_link_status)
2716 vogl::vector<GLchar> log;
2718 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2721 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2728 GLint actual_length = 0;
2729 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2736 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2743 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2748 if ((log.size()) && (log[0]))
2750 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
2754 if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2756 process_entrypoint_warning("%s: Number of trace active attributes (%i) differs from number of replay active attributes (%i) after linking program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_active_attributes, replay_active_attributes, trace_handle, replay_handle);
2759 const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2763 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2764 if (it == get_shared_state()->m_glsl_program_hash_map.end())
2765 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2766 glsl_program_state &prog_state = it->second;
2768 for (uint i = 0; i < pUniforms_node->size(); i++)
2770 const json_node *pUniform = pUniforms_node->get_child(i);
2777 const char *pName = pUniform->value_as_string_ptr("name");
2783 int trace_loc = pUniform->value_as_int("location");
2784 int trace_array_size = pUniform->value_as_int("size");
2785 //int trace_type = pUniform->value_as_int("type");
2787 VOGL_ASSERT(trace_array_size >= 1);
2789 if ((trace_loc < 0) || (trace_array_size <= 0))
2792 if (trace_array_size > 1)
2794 dynamic_string element_name;
2795 for (int i = 0; i < trace_array_size; i++)
2797 element_name = pName;
2798 int start_bracket_ofs = element_name.find_right('[');
2799 if (start_bracket_ofs >= 0)
2800 element_name.left(start_bracket_ofs);
2801 element_name.format_append("[%u]", i);
2803 GLint element_trace_loc = trace_loc + i;
2804 GLint element_replay_loc;
2805 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2806 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2808 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2811 if (element_replay_loc < 0)
2813 process_entrypoint_warning("%s: glGetUniformLocation: Trace active array uniform %s trace location %i trace array size %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, element_name.get_ptr(), trace_loc, trace_array_size, trace_handle, replay_handle);
2817 prog_state.m_uniform_locations.erase(element_trace_loc);
2818 prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2822 else if (trace_array_size == 1)
2825 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2826 replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2828 replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2833 process_entrypoint_warning("%s: glGetUniformLocation: Trace active uniform %s trace location %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, pName, trace_loc, trace_handle, replay_handle);
2837 prog_state.m_uniform_locations.erase(trace_loc);
2838 prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2845 //----------------------------------------------------------------------------------------------------------------------
2846 // vogl_gl_replayer::post_draw_call
2847 // Called after each draw call or blit.
2848 //----------------------------------------------------------------------------------------------------------------------
2849 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2853 if (m_pCur_context_state->m_inside_gl_begin)
2856 if (check_gl_error())
2857 return cStatusGLError;
2859 bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2861 if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2863 dump_current_shaders();
2866 if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2868 bool should_dump = false;
2870 if (m_dump_framebuffer_on_draw_frame_index != -1)
2872 if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2875 else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2877 should_dump = math::is_within_closed_range<uint64_t>(m_last_parsed_call_counter, m_dump_framebuffer_on_draw_first_gl_call_index, m_dump_framebuffer_on_draw_last_gl_call_index);
2886 dump_current_framebuffer();
2890 m_frame_draw_counter += is_draw;
2895 //----------------------------------------------------------------------------------------------------------------------
2896 // vogl_gl_replayer::dump_framebuffer
2897 //----------------------------------------------------------------------------------------------------------------------
2898 bool vogl_gl_replayer::dump_framebuffer(uint width, uint height, GLuint read_framebuffer, GLenum read_buffer, GLenum internal_format, uint orig_samples, GLuint replay_texture, GLuint replay_rbo)
2902 uint trace_read_framebuffer = 0;
2903 if (read_framebuffer)
2905 gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2906 if (it != get_context_state()->m_framebuffers.end())
2907 trace_read_framebuffer = it->second;
2910 uint trace_texture = replay_texture;
2913 if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2914 vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2920 if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2921 vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2924 m_screenshot_buffer.resize(width * height * 3);
2926 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, read_framebuffer, read_buffer, 0);
2930 process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2934 size_t png_size = 0;
2935 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2937 dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2938 m_dump_framebuffer_on_draw_prefix.get_ptr(),
2939 (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2940 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2942 (unsigned long long)m_frame_draw_counter,
2944 trace_read_framebuffer,
2945 g_gl_enums.find_gl_name(read_buffer));
2947 if (internal_format != GL_NONE)
2949 screenshot_filename += "_";
2950 screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2953 if (orig_samples != 0)
2954 screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2956 screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2958 screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2960 screenshot_filename += ".png";
2962 file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2964 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2966 process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2971 vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2979 //----------------------------------------------------------------------------------------------------------------------
2980 // vogl_gl_replayer::dump_current_framebuffer
2981 //----------------------------------------------------------------------------------------------------------------------
2982 void vogl_gl_replayer::dump_current_framebuffer()
2986 uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
2988 uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
2989 if (!max_draw_buffers)
2991 process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
2995 //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
2997 vogl::vector<GLenum> draw_buffers(max_draw_buffers);
2998 for (uint i = 0; i < max_draw_buffers; i++)
2999 draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3001 if (!draw_framebuffer_binding)
3003 for (uint i = 0; i < max_draw_buffers; i++)
3004 if (draw_buffers[i] != GL_NONE)
3005 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3009 // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3010 vogl_framebuffer_state fbo_state;
3011 if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3013 process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3017 for (uint i = 0; i < draw_buffers.size(); i++)
3019 if (draw_buffers[i] == GL_NONE)
3022 const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3025 process_entrypoint_warning("%s: Can't find draw buffer %s in currently bound FBO %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(draw_buffers[i]), draw_framebuffer_binding);
3029 if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3031 else if (pAttachment->get_type() == GL_RENDERBUFFER)
3033 GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3037 vogl_renderbuffer_state rbo_state;
3038 if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3040 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3044 if (rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_DEPTH_SIZE) || rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_STENCIL_SIZE))
3047 uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3048 uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3049 uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3050 GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3052 if ((!width) || (!height) || (!internal_format))
3054 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's RBO %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3060 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3062 GLuint temp_rbo = 0;
3063 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3069 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3072 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3075 GLuint temp_fbo = 0;
3076 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3079 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3082 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3085 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3086 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3089 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3092 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3095 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3097 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3100 // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3101 vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3103 GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3106 GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3108 if (!check_gl_error())
3109 dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3112 process_entrypoint_warning("%s: Failed downsampling FBO %u color attachment %u's RBO %u to temporary RBO\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3116 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3119 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3122 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3125 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3130 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3133 else if (pAttachment->get_type() == GL_TEXTURE)
3135 GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3138 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3142 GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3143 if (target == GL_NONE)
3145 process_entrypoint_warning("%s: Current FBO %u first color attachment's type is GL_TEXTURE, but unable to determine the texture's target type, GL texture handle %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding, tex_handle);
3149 if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3150 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3152 if (!utils::is_in_set<GLenum, GLenum>(target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY))
3154 process_entrypoint_warning("%s: Unsupported FBO attachment texture target type (%s), GL texture handle %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(target), tex_handle);
3158 uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3159 uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3160 VOGL_NOTE_UNUSED(layer);
3162 GLint width = 0, height = 0, samples = 0;
3163 GLenum internal_format = GL_NONE;
3166 vogl_scoped_binding_state binding_saver;
3167 binding_saver.save_textures();
3169 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3172 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3175 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3178 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3181 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3183 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3188 if ((!width) || (!height))
3190 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's texture %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, tex_handle);
3196 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3200 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3205 //----------------------------------------------------------------------------------------------------------------------
3206 // vogl_gl_replayer::dump_current_shaders
3207 //----------------------------------------------------------------------------------------------------------------------
3208 void vogl_gl_replayer::dump_current_shaders()
3212 if (!m_pCur_context_state)
3217 const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3219 // Get the current program.
3220 GLuint current_program = 0;
3221 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(¤t_program));
3224 VOGL_ASSERT(replay_program == current_program);
3226 if (!current_program)
3229 // Get the attached shaders.
3230 GLsizei attached_shader_count = -1;
3231 GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3234 if (!attached_shader_count)
3237 vogl::vector<GLuint> shaders(attached_shader_count);
3238 GLsizei actual_shader_count = 0;
3239 GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3240 attached_shader_count,
3241 &actual_shader_count,
3245 VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3247 vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3248 cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3249 replay_program, m_pCur_context_state->m_cur_trace_program,
3250 attached_shader_count);
3252 // Get source from shaders.
3253 vogl::vector<GLchar> source; // Shared buffer for each iteration.
3254 for (GLsizei i = 0; i < attached_shader_count; ++i)
3256 const GLuint shader = shaders[i];
3257 GLint shader_type = 0;
3258 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3261 vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3263 GLint source_length = -1; // Includes NUL terminator.
3264 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3267 VOGL_ASSERT(source_length > 0);
3269 source.resize(source_length);
3270 GLint actual_length = 0; // Excludes NUL terminator!
3271 GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3274 VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3275 vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3277 vogl_printf("========\n");
3280 //----------------------------------------------------------------------------------------------------------------------
3281 // vogl_gl_replayer::handle_ShaderSource
3282 // Handle ShaderSource and ShaderSourceARB.
3283 //----------------------------------------------------------------------------------------------------------------------
3284 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3286 const vogl_client_memory_array trace_strings_glchar_ptr_array,
3287 const GLint *pTrace_lengths)
3291 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3293 // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3294 const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3295 const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3297 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3298 (trace_strings_count != static_cast<uint>(count)))
3300 process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3301 VOGL_METHOD_NAME, count, trace_strings_count);
3302 return cStatusHardFailure;
3305 if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3307 process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3308 VOGL_METHOD_NAME, count, trace_lengths_count);
3309 return cStatusHardFailure;
3312 vogl::vector<const GLcharARB *> strings(count);
3313 vogl::vector<GLint> lengths(count);
3315 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3317 vogl::vector<uint8_vec> blobs(count);
3319 for (GLsizei i = 0; i < count; i++)
3322 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3323 (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3328 lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3330 key_value_map::const_iterator it = map.find(i);
3331 if (it == map.end())
3335 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3336 VOGL_METHOD_NAME, i);
3337 return cStatusHardFailure;
3342 const uint8_vec *pBlob = it->second.get_blob();
3345 process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3346 return cStatusHardFailure;
3350 uint8_vec &blob = blobs[i];
3352 if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3354 if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3356 process_entrypoint_warning("%s: Length value (%u) stored in length array at index %u doesn't match string %u's length - changing to match\n", VOGL_METHOD_NAME, pTrace_lengths[i], i, blob.size());
3357 lengths[i] = blob.size();
3362 if ((blob.size()) && (blob.back() != '\0'))
3364 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3366 blob.push_back('\0');
3369 VOGL_ASSERT(blob.size() &&
3370 (blob.back() == '\0') &&
3371 (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3374 strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3377 if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3379 GL_ENTRYPOINT(glShaderSource)(replay_object,
3381 trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3382 pTrace_lengths ? lengths.get_ptr() : NULL);
3386 GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3388 trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3389 pTrace_lengths ? lengths.get_ptr() : NULL);
3394 //----------------------------------------------------------------------------------------------------------------------
3395 // vogl_gl_replayer::display_list_bind_callback
3396 // handle is in the trace namespace
3397 //----------------------------------------------------------------------------------------------------------------------
3398 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3402 vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3404 if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3406 if ((handle) && (target != GL_NONE))
3408 // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3409 pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3414 // TODO - right now the display list whitelist doens't let anything else get bound.
3415 pReplayer->process_entrypoint_warning("%s: Unsupported bind in display lists, namespace %s target %s trace handle %u\n", VOGL_FUNCTION_NAME, vogl_get_namespace_name(handle_namespace), g_gl_enums.find_gl_name(target), handle);
3419 //----------------------------------------------------------------------------------------------------------------------
3420 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3421 //----------------------------------------------------------------------------------------------------------------------
3422 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...) \
3423 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3424 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3426 result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3428 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...) \
3429 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3430 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3431 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3432 result = GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3434 result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3436 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...) \
3437 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3438 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3440 GL_ENTRYPOINT(e1)(__VA_ARGS__);
3442 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...) \
3443 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3444 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3445 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3446 GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3448 GL_ENTRYPOINT(e2)(__VA_ARGS__);
3450 //----------------------------------------------------------------------------------------------------------------------
3451 // vogl_replayer::process_gl_entrypoint_packet
3452 // This will be called during replaying, or when building display lists during state restoring.
3453 //----------------------------------------------------------------------------------------------------------------------
3454 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3456 m_pCur_gl_packet = &trace_packet;
3458 status_t status = cStatusOK;
3460 if (m_pPending_snapshot)
3462 status = process_applying_pending_snapshot();
3463 if (status != cStatusOK)
3467 if (m_pending_make_current_packet.is_valid())
3469 status = process_pending_make_current();
3470 if (status != cStatusOK)
3474 const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3476 m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3478 status = process_gl_entrypoint_packet_internal(trace_packet);
3480 if (status != cStatusResizeWindow)
3481 m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3483 m_pCur_gl_packet = NULL;
3488 //----------------------------------------------------------------------------------------------------------------------
3489 // vogl_replayer::process_gl_entrypoint_packet_internal
3490 // This will be called during replaying, or when building display lists during state restoring.
3491 //----------------------------------------------------------------------------------------------------------------------
3492 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3496 m_at_frame_boundary = false;
3498 const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3499 const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3501 if (m_flags & cGLReplayerDebugMode)
3502 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3504 if (m_flags & cGLReplayerDebugMode)
3505 dump_packet_as_func_call(trace_packet);
3507 if (m_flags & cGLReplayerDumpAllPackets)
3508 print_detailed_context(cDebugConsoleMessage);
3510 if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3511 return process_internal_trace_command(gl_entrypoint_packet);
3513 status_t status = cStatusOK;
3515 if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3517 status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3518 if (status != cStatusOK)
3522 bool processed_glx_packet = true;
3523 switch (entrypoint_id)
3525 case VOGL_ENTRYPOINT_glXDestroyContext:
3527 const Display *dpy = m_pWindow->get_display();
3529 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3530 GLXContext replay_context = remap_context(trace_context);
3532 if ((trace_context) && (!replay_context))
3534 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3535 return cStatusHardFailure;
3538 if (trace_context == m_cur_trace_context)
3540 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3541 VOGL_METHOD_NAME, (uint64_t)trace_context);
3543 m_cur_trace_context = 0;
3544 m_cur_replay_context = 0;
3545 m_pCur_context_state = NULL;
3548 GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3550 destroy_context(trace_context);
3554 case VOGL_ENTRYPOINT_glXMakeCurrent:
3555 case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3557 Bool trace_result = trace_packet.get_return_value<Bool>();
3559 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3561 // pContext_state can be NULL!
3562 context_state *pContext_state = get_trace_context_state(trace_context);
3563 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3565 if ((trace_context) && (!replay_context))
3567 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3568 return cStatusHardFailure;
3571 int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3572 VOGL_NOTE_UNUSED(viewport_x);
3573 int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3574 VOGL_NOTE_UNUSED(viewport_y);
3575 int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3576 VOGL_NOTE_UNUSED(viewport_width);
3577 int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3578 VOGL_NOTE_UNUSED(viewport_height);
3579 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3580 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3582 // We may need to defer the make current until the window is the proper size, because the initial GL viewport's state depends on the Window size. Ugh.
3583 if ((trace_context) && (trace_result))
3585 if ((win_width) && (win_height))
3587 if (!(m_flags & cGLReplayerLockWindowDimensions))
3589 if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3591 m_pending_make_current_packet = *m_pCur_gl_packet;
3593 status = trigger_pending_window_resize(win_width, win_height);
3595 vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3601 if (status != cStatusResizeWindow)
3603 const Display *dpy = m_pWindow->get_display();
3604 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3606 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3611 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3612 return cStatusHardFailure;
3616 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3621 m_cur_trace_context = trace_context;
3622 m_cur_replay_context = replay_context;
3623 m_pCur_context_state = pContext_state;
3627 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3631 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3632 viewport_x, viewport_y,
3633 viewport_width, viewport_height,
3634 win_width, win_height);
3637 if (m_cur_replay_context)
3639 if (!handle_context_made_current())
3640 return cStatusHardFailure;
3647 case VOGL_ENTRYPOINT_glXQueryVersion:
3649 int major = 0, minor = 0;
3650 Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3651 process_entrypoint_message("%s: glXQueryVersion returned major %u minor %u status %u, trace recorded major %u minor %u status %u\n", VOGL_METHOD_NAME, major, minor, status,
3652 *trace_packet.get_param_client_memory<int>(1),
3653 *trace_packet.get_param_client_memory<int>(2),
3654 trace_packet.get_return_value<Bool>());
3658 case VOGL_ENTRYPOINT_glXChooseFBConfig:
3663 case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3668 case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3673 case VOGL_ENTRYPOINT_glXGetProcAddress:
3674 case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3676 const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3677 vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3679 void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3681 if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3683 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3684 (const char *)procName,
3685 (pFunc != NULL) ? "succeeded" : "failed",
3686 (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3691 case VOGL_ENTRYPOINT_glXCreateNewContext:
3693 Display *dpy = m_pWindow->get_display();
3694 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3695 int render_type = trace_packet.get_param_value<GLint>(2);
3697 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3698 GLXContext replay_share_context = remap_context(trace_share_context);
3700 if ((trace_share_context) && (!replay_share_context))
3702 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3705 Bool direct = trace_packet.get_param_value<Bool>(4);
3706 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3708 if (m_flags & cGLReplayerForceDebugContexts)
3710 process_entrypoint_warning("%s: glxCreateNewContext() called but we're trying to force debug contexts, which requires us to call glXCreateContextAttribsARB(). This may fail if the user has called glXCreateWindow().\n", VOGL_METHOD_NAME);
3712 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3713 if (status != cStatusOK)
3718 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3720 if (!replay_context)
3724 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3725 return cStatusHardFailure;
3729 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3737 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3738 VOGL_NOTE_UNUSED(pContext_state);
3742 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3749 case VOGL_ENTRYPOINT_glXCreateContext:
3751 Display *dpy = m_pWindow->get_display();
3753 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3754 GLXContext replay_share_context = remap_context(trace_share_context);
3756 if ((trace_share_context) && (!replay_share_context))
3758 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3761 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3762 Bool direct = trace_packet.get_param_value<Bool>(3);
3763 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3765 if (m_flags & cGLReplayerForceDebugContexts)
3767 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3768 if (status != cStatusOK)
3773 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3775 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3777 if (!replay_context)
3781 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3782 return cStatusHardFailure;
3786 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3794 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3795 VOGL_NOTE_UNUSED(pContext_state);
3799 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3806 case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3808 Display *dpy = m_pWindow->get_display();
3809 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3811 vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3812 GLXContext replay_share_context = remap_context(trace_share_context);
3814 if ((trace_share_context) && (!replay_share_context))
3816 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3819 Bool direct = trace_packet.get_param_value<Bool>(3);
3820 const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3821 const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3823 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3825 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3826 if (status != cStatusOK)
3831 case VOGL_ENTRYPOINT_glXSwapBuffers:
3833 check_program_binding_shadow();
3835 if (m_flags & cGLReplayerLowLevelDebugMode)
3837 if (!validate_program_and_shader_handle_tables())
3838 vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3839 if (!validate_textures())
3840 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3843 const Display *dpy = m_pWindow->get_display();
3844 GLXDrawable drawable = m_pWindow->get_xwindow();
3846 if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3848 snapshot_backbuffer();
3851 if (m_dump_frontbuffer_filename.has_content())
3853 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3854 m_dump_frontbuffer_filename.clear();
3857 GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3859 if (m_swap_sleep_time)
3860 vogl_sleep(m_swap_sleep_time);
3862 status = cStatusNextFrame;
3864 m_at_frame_boundary = true;
3866 if (m_flags & cGLReplayerDebugMode)
3868 vogl_debug_printf("%s: glXSwapBuffers() processed at end of frame %u, swap %u, last GL call counter %" PRIu64 "\n", VOGL_METHOD_NAME, m_frame_index, m_total_swaps, m_last_parsed_call_counter);
3874 m_frame_draw_counter = 0;
3876 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3877 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3878 if ((win_width) && (win_height))
3880 if (!(m_flags & cGLReplayerLockWindowDimensions))
3882 if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3884 // TODO: This resize might need to be deferred until the window system actually resizes the window.
3885 //m_pWindow->resize(win_width, win_height);
3886 trigger_pending_window_resize(win_width, win_height);
3888 vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3895 case VOGL_ENTRYPOINT_glXWaitX:
3897 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3899 VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3903 case VOGL_ENTRYPOINT_glXWaitGL:
3905 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3907 VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3911 case VOGL_ENTRYPOINT_glXIsDirect:
3913 const Display *dpy = m_pWindow->get_display();
3915 vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3916 GLXContext replay_context = remap_context(trace_context);
3918 Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3919 Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3921 if (replay_is_direct != trace_is_direct)
3923 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3928 case VOGL_ENTRYPOINT_glXGetCurrentContext:
3930 GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3931 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3933 if ((replay_context != 0) != (trace_context != 0))
3935 process_entrypoint_warning("%s: glXGetCurrentContext() returned different results while replaying (0x%" PRIX64 ") vs tracing (0x%" PRIX64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_context, (uint64_t)trace_context);
3940 case VOGL_ENTRYPOINT_glXCreateWindow:
3941 case VOGL_ENTRYPOINT_glXDestroyWindow:
3942 case VOGL_ENTRYPOINT_glXChooseVisual:
3943 case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3944 case VOGL_ENTRYPOINT_glXQueryDrawable:
3945 case VOGL_ENTRYPOINT_glXQueryExtension:
3946 case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3947 case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3948 case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3949 case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3950 case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3951 case VOGL_ENTRYPOINT_glXQueryContext:
3952 case VOGL_ENTRYPOINT_glXGetClientString:
3953 case VOGL_ENTRYPOINT_glXGetConfig:
3954 case VOGL_ENTRYPOINT_glXGetFBConfigs:
3961 processed_glx_packet = false;
3966 if (processed_glx_packet)
3968 // TODO: Check for GLX errors?
3972 if (!m_cur_replay_context)
3974 process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
3975 return cStatusSoftFailure;
3978 VOGL_ASSERT(m_pCur_context_state);
3979 m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
3981 #ifdef VOGL_BUILD_DEBUG
3982 VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
3985 // Add call to current display list
3986 if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
3988 if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
3990 if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
3991 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not listable.\n", VOGL_FUNCTION_NAME);
3993 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
3997 if (!get_shared_state()->m_shadow_state.m_display_lists.add_packet_to_list(get_context_state()->m_current_display_list_handle, entrypoint_id, trace_packet))
3999 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4004 switch (entrypoint_id)
4006 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4007 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4008 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4009 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4010 case VOGL_ENTRYPOINT_##name: \
4011 { GL_ENTRYPOINT(name)(
4012 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4013 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4014 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4015 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4018 #include "gl_glx_simple_replay_funcs.inc"
4019 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4020 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4021 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4022 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4023 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4025 case VOGL_ENTRYPOINT_glXUseXFont:
4027 const key_value_map &key_value_map = trace_packet.get_key_value_map();
4029 const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4030 if ((!pFont_name) || (pFont_name->is_empty()))
4032 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4036 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4039 process_entrypoint_warning("%s: Couldn't load X font %s - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4043 GLint first = trace_packet.get_param_value<int>(1);
4044 GLint count = trace_packet.get_param_value<int>(2);
4045 int trace_list_base = trace_packet.get_param_value<int>(3);
4046 GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4048 GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4050 XFreeFont(m_pWindow->get_display(), pFont);
4052 if (get_context_state()->is_composing_display_list())
4054 process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4058 if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4060 process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4068 case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4070 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4072 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4074 if ((status = post_draw_call()) != cStatusOK)
4079 case VOGL_ENTRYPOINT_glBlitFramebuffer:
4081 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4083 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4085 if ((status = post_draw_call()) != cStatusOK)
4090 case VOGL_ENTRYPOINT_glBegin:
4092 if (m_pCur_context_state->m_inside_gl_begin)
4094 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4096 m_pCur_context_state->m_inside_gl_begin = true;
4098 g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4102 case VOGL_ENTRYPOINT_glEnd:
4104 if (!m_pCur_context_state->m_inside_gl_begin)
4106 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4108 m_pCur_context_state->m_inside_gl_begin = false;
4110 g_vogl_actual_gl_entrypoints.m_glEnd();
4112 if ((status = post_draw_call()) != cStatusOK)
4117 case VOGL_ENTRYPOINT_glGetError:
4119 // TODO: Compare trace error vs. replay error
4123 case VOGL_ENTRYPOINT_glGetStringi:
4125 if (!benchmark_mode())
4127 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4128 trace_packet.get_param_value<GLenum>(0),
4129 trace_packet.get_param_value<GLuint>(1));
4130 VOGL_NOTE_UNUSED(pStr);
4132 // TODO: Compare vs. trace's?
4137 case VOGL_ENTRYPOINT_glGetString:
4139 if (!benchmark_mode())
4141 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4142 trace_packet.get_param_value<GLenum>(0));
4143 VOGL_NOTE_UNUSED(pStr);
4145 // TODO: Compare vs. trace's?
4150 case VOGL_ENTRYPOINT_glGenFramebuffers:
4151 case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4153 if (!gen_handles(get_context_state()->m_framebuffers,
4154 trace_packet.get_param_value<GLsizei>(0),
4155 static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4156 (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4157 return cStatusHardFailure;
4161 case VOGL_ENTRYPOINT_glBindFramebuffer:
4162 case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4164 GLenum target = trace_packet.get_param_value<GLenum>(0);
4165 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4167 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4169 SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4173 case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4174 case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4176 if (!benchmark_mode())
4178 GLenum target = trace_packet.get_param_value<GLenum>(0);
4179 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4180 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4181 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4182 uint trace_params_count = trace_params_size / sizeof(GLint);
4184 int n = g_gl_enums.get_pname_count(pname);
4187 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4188 return cStatusSoftFailure;
4190 else if (n < static_cast<int>(trace_params_count))
4192 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);
4193 return cStatusSoftFailure;
4197 vogl::growable_array<GLint, 16> params(n + 1);
4198 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4200 SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4202 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4204 if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4206 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));
4213 case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4214 case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4217 SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4219 GLenum trace_status = trace_packet.get_return_value<GLenum>();
4220 if (result != trace_status)
4222 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4226 case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4228 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));
4231 case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4233 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));
4236 case VOGL_ENTRYPOINT_glFramebufferTexture:
4238 GLenum target = trace_packet.get_param_value<GLenum>(0);
4239 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4240 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4241 GLuint replay_texture = trace_texture;
4242 GLint level = trace_packet.get_param_value<GLint>(3);
4244 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4247 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);
4250 GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4254 case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4255 case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4257 GLenum target = trace_packet.get_param_value<GLenum>(0);
4258 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4259 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4260 GLuint replay_texture = trace_texture;
4261 GLint level = trace_packet.get_param_value<GLint>(3);
4262 GLint layer = trace_packet.get_param_value<GLint>(4);
4264 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4267 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);
4270 SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4274 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4275 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4276 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4277 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4278 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4279 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4281 GLenum target = trace_packet.get_param_value<GLenum>(0);
4282 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4283 GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4284 GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4285 GLuint replay_texture = trace_texture;
4286 GLint level = trace_packet.get_param_value<GLint>(4);
4288 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4291 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);
4294 switch (entrypoint_id)
4296 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4297 GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4299 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4300 GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4302 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4303 GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4305 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4306 GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4308 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4309 GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4311 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4312 GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4320 case VOGL_ENTRYPOINT_glGenTextures:
4322 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))
4323 return cStatusHardFailure;
4326 case VOGL_ENTRYPOINT_glGenTexturesEXT:
4328 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))
4329 return cStatusHardFailure;
4332 case VOGL_ENTRYPOINT_glDeleteTextures:
4334 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));
4337 case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4339 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));
4342 case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4344 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4346 GLuint trace_texture = texture;
4347 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4349 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4352 VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4354 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4356 if (!check_gl_error())
4357 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4362 case VOGL_ENTRYPOINT_glBindTexture:
4363 case VOGL_ENTRYPOINT_glBindTextureEXT:
4365 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4367 GLuint trace_texture = texture;
4368 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4370 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4373 SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4375 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4377 if (!check_gl_error())
4378 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4383 case VOGL_ENTRYPOINT_glBindSampler:
4385 GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4386 GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4389 case VOGL_ENTRYPOINT_glDeleteSamplers:
4391 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));
4394 case VOGL_ENTRYPOINT_glGenSamplers:
4396 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))
4397 return cStatusHardFailure;
4401 case VOGL_ENTRYPOINT_glSamplerParameterf:
4403 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4404 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4405 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4408 case VOGL_ENTRYPOINT_glSamplerParameteri:
4410 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4411 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4412 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4415 case VOGL_ENTRYPOINT_glSamplerParameterfv:
4417 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4418 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4419 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4422 case VOGL_ENTRYPOINT_glSamplerParameteriv:
4424 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4425 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4426 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4429 case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4431 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4432 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4433 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4436 case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4438 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4439 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4440 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4443 case VOGL_ENTRYPOINT_glGenBuffers:
4444 case VOGL_ENTRYPOINT_glGenBuffersARB:
4446 uint n = trace_packet.get_param_value<GLsizei>(0);
4447 const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4449 if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4451 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4452 return cStatusHardFailure;
4456 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4457 return cStatusHardFailure;
4462 for (uint i = 0; i < n; i++)
4464 if (pTrace_handles[i])
4465 get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4471 case VOGL_ENTRYPOINT_glDeleteBuffers:
4472 case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4474 GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4475 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4476 uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4478 if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4480 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4481 return cStatusHardFailure;
4484 for (GLsizei iter = 0; iter < trace_n; iter++)
4486 GLuint trace_id = pTrace_ids[iter];
4490 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4492 process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4495 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4496 if (it == get_shared_state()->m_buffers.end())
4498 process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4502 GLuint replay_id = it->second;
4504 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4506 for (uint i = 0; i < mapped_bufs.size(); i++)
4508 if (mapped_bufs[i].m_buffer == replay_id)
4510 process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4512 mapped_bufs.erase_unordered(i);
4518 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4519 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4521 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4525 case VOGL_ENTRYPOINT_glGenProgramsARB:
4527 // arb program objects
4528 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4530 if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4531 return cStatusHardFailure;
4533 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4534 if (pTrace_programs[i])
4535 get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4539 case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4541 // arb program objects
4542 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4544 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4545 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4547 delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4550 case VOGL_ENTRYPOINT_glBindProgramARB:
4552 // arb program objects
4553 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4555 GLuint trace_program = program;
4556 gl_handle_hash_map::const_iterator it;
4559 it = get_shared_state()->m_arb_programs.find(program);
4560 if (it != get_shared_state()->m_arb_programs.end())
4561 program = it->second;
4563 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);
4568 VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4570 if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4574 if (it == get_shared_state()->m_arb_programs.end())
4575 get_shared_state()->m_arb_programs.insert(trace_program, program);
4577 get_shared_state()->m_arb_program_targets[trace_program] = target;
4582 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));
4583 return cStatusGLError;
4588 case VOGL_ENTRYPOINT_glIsProgramARB:
4590 if (!benchmark_mode())
4592 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4594 GLuint trace_program = program;
4595 program = map_handle(get_shared_state()->m_arb_programs, program);
4597 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4598 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4600 if (trace_result != replay_result)
4601 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);
4606 case VOGL_ENTRYPOINT_glGenQueries:
4607 case VOGL_ENTRYPOINT_glGenQueriesARB:
4609 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4610 vogl::growable_array<GLuint, 16> replay_handles(n);
4612 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()))
4613 return cStatusHardFailure;
4615 for (GLsizei i = 0; i < n; i++)
4616 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4620 case VOGL_ENTRYPOINT_glDeleteQueries:
4621 case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4623 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4624 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4628 for (GLsizei i = 0; i < n; i++)
4630 GLuint trace_id = pTrace_ids[i];
4633 gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4634 if (it != get_shared_state()->m_queries.end())
4635 get_shared_state()->m_query_targets.erase(it->second);
4639 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4640 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));
4642 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));
4646 case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4648 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))
4649 return cStatusHardFailure;
4652 case VOGL_ENTRYPOINT_glGenRenderbuffers:
4654 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))
4655 return cStatusHardFailure;
4658 case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4660 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));
4663 case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4665 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));
4668 case VOGL_ENTRYPOINT_glIsRenderbuffer:
4670 if (!benchmark_mode())
4672 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4673 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4674 if (replay_result != trace_result)
4676 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);
4681 case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4683 if (!benchmark_mode())
4685 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4686 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4687 if (replay_result != trace_result)
4689 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);
4694 case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4696 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)));
4699 case VOGL_ENTRYPOINT_glBindRenderbuffer:
4701 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)));
4704 case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4706 GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4707 trace_packet.get_param_value<GLenum>(0),
4708 trace_packet.get_param_value<GLenum>(1),
4709 trace_packet.get_param_value<GLenum>(2),
4710 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4713 case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4715 GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4716 trace_packet.get_param_value<GLenum>(0),
4717 trace_packet.get_param_value<GLenum>(1),
4718 trace_packet.get_param_value<GLenum>(2),
4719 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4722 case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4723 case VOGL_ENTRYPOINT_glUseProgram:
4725 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4726 handle_use_program(trace_handle, entrypoint_id);
4729 case VOGL_ENTRYPOINT_glProgramParameteri:
4730 case VOGL_ENTRYPOINT_glProgramParameteriARB:
4731 case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4733 VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4735 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4737 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4738 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4739 else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4740 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4742 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4746 case VOGL_ENTRYPOINT_glBindFragDataLocation:
4747 case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4749 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4751 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4753 if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4754 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4756 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4760 case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4762 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4764 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4766 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4770 case VOGL_ENTRYPOINT_glValidateProgramARB:
4772 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4774 programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4776 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4780 case VOGL_ENTRYPOINT_glValidateProgram:
4782 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4784 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4786 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4790 case VOGL_ENTRYPOINT_glCreateProgram:
4791 case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4793 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4796 GLuint replay_handle;
4798 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4799 replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4801 replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4803 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4805 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4806 return cStatusHardFailure;
4810 case VOGL_ENTRYPOINT_glDeleteProgram:
4812 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4813 handle_delete_program(trace_handle);
4817 case VOGL_ENTRYPOINT_glDeleteObjectARB:
4819 GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4820 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4822 if (target == VOGL_SHADER_OBJECT)
4823 handle_delete_shader(trace_handle);
4824 else if (target == VOGL_PROGRAM_OBJECT)
4825 handle_delete_program(trace_handle);
4828 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4830 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);
4831 return cStatusSoftFailure;
4836 case VOGL_ENTRYPOINT_glDeleteShader:
4838 GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4839 handle_delete_shader(trace_shader);
4843 case VOGL_ENTRYPOINT_glCreateShader:
4844 case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4846 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4849 GLuint replay_handle;
4851 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4852 replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4854 replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4856 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4858 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4859 return cStatusHardFailure;
4863 case VOGL_ENTRYPOINT_glAttachShader:
4865 GL_ENTRYPOINT(glAttachShader)(
4866 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4867 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4870 case VOGL_ENTRYPOINT_glAttachObjectARB:
4872 GL_ENTRYPOINT(glAttachObjectARB)(
4873 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4874 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4877 case VOGL_ENTRYPOINT_glDetachShader:
4879 handle_detach_shader(entrypoint_id);
4883 case VOGL_ENTRYPOINT_glDetachObjectARB:
4885 GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4887 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4889 if (target == VOGL_SHADER_OBJECT)
4890 handle_detach_shader(entrypoint_id);
4893 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4894 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4899 case VOGL_ENTRYPOINT_glBindAttribLocation:
4901 GL_ENTRYPOINT(glBindAttribLocation)(
4902 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4903 trace_packet.get_param_value<GLuint>(1),
4904 trace_packet.get_param_client_memory<GLchar>(2));
4907 case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4909 GL_ENTRYPOINT(glBindAttribLocationARB)(
4910 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4911 trace_packet.get_param_value<GLuint>(1),
4912 trace_packet.get_param_client_memory<GLcharARB>(2));
4915 case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4917 if (!benchmark_mode())
4919 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4920 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4922 int n = g_gl_enums.get_pname_count(pname);
4925 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4926 return cStatusSoftFailure;
4930 vogl::growable_array<GLint, 16> params(n + 1);
4931 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4933 GL_ENTRYPOINT(glGetObjectParameterivARB)(
4934 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4938 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4940 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4942 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));
4948 case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4950 if (!benchmark_mode())
4952 GLenum target = trace_packet.get_param_value<GLenum>(0);
4953 GLenum value = trace_packet.get_param_value<GLenum>(1);
4954 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4956 int n = g_gl_enums.get_pname_count(value);
4959 process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4960 return cStatusSoftFailure;
4964 vogl::growable_array<GLint, 16> data(n + 1);
4965 data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4967 GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4969 VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4971 GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
4972 if (data[0] != trace_data)
4974 process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
4975 vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
4983 case VOGL_ENTRYPOINT_glGetBufferPointerv:
4985 if (!benchmark_mode())
4987 GLvoid *pReplay_ptr = NULL;
4988 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
4990 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
4991 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;
4993 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
4995 process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
4996 vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
5002 case VOGL_ENTRYPOINT_glShaderSource:
5003 case VOGL_ENTRYPOINT_glShaderSourceARB:
5005 const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5006 trace_packet.get_param_value<GLsizei>(1),
5007 trace_packet.get_param_client_memory_array(2),
5008 trace_packet.get_param_client_memory<const GLint>(3));
5009 if (status != cStatusOK)
5013 case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5015 GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5016 GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5019 GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5022 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5023 return cStatusSoftFailure;
5027 vogl::vector<GLchar> log(length);
5029 GLsizei actual_length = 0;
5030 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5034 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());
5040 case VOGL_ENTRYPOINT_glGetPointerv:
5042 if (!benchmark_mode())
5045 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5047 // TODO: Differ vs. trace's in some way?
5052 case VOGL_ENTRYPOINT_glGetInfoLogARB:
5054 GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5055 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5057 GLsizei length = -1;
5058 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5061 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5062 return cStatusSoftFailure;
5066 vogl::vector<GLcharARB> log(length);
5068 GLsizei actual_length = 0;
5069 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5073 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());
5079 case VOGL_ENTRYPOINT_glGetUniformLocation:
5081 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5082 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5083 GLint trace_loc = trace_packet.get_return_value<GLint>();
5087 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5089 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5093 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);
5098 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);
5101 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5102 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5103 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5105 glsl_program_state &state = it->second;
5106 state.m_uniform_locations.erase(trace_loc);
5107 state.m_uniform_locations.insert(trace_loc, replay_loc);
5114 case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5116 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5117 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5118 GLint trace_loc = trace_packet.get_return_value<GLint>();
5122 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5124 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5128 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);
5133 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);
5136 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5137 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5138 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5140 glsl_program_state &state = it->second;
5141 state.m_uniform_locations.erase(trace_loc);
5142 state.m_uniform_locations.insert(trace_loc, replay_loc);
5149 case VOGL_ENTRYPOINT_glGetActiveAttrib:
5150 case VOGL_ENTRYPOINT_glGetActiveUniform:
5152 if (!benchmark_mode())
5154 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5155 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5157 GLuint index = trace_packet.get_param_value<GLuint>(1);
5158 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5160 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5161 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5162 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5163 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5165 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5171 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5172 GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5174 GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5176 bool mismatch = false;
5178 GLsizei trace_len = 0;
5181 trace_len = pTrace_length[0];
5182 if (trace_len != len)
5186 GLint trace_size = 0;
5189 trace_size = pTrace_size[0];
5190 if (trace_size != size)
5194 GLenum trace_type = 0;
5197 trace_type = pTrace_type[0];
5198 if (trace_type != type)
5202 if ((bufSize) && (pTrace_name))
5204 uint n = vogl_strlen((const char *)pTrace_name) + 1;
5205 if (bufSize < (GLsizei)n)
5207 else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5213 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5214 vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5215 (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5216 vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5217 (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5223 case VOGL_ENTRYPOINT_glGetAttachedShaders:
5225 if (!benchmark_mode())
5227 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5228 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5230 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5232 vogl::growable_array<GLuint, 16> shaders(max_count);
5234 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5236 // TODO: Diff results
5241 case VOGL_ENTRYPOINT_glGetAttribLocation:
5243 if (!benchmark_mode())
5245 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5246 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5248 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5250 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5251 GLint trace_result = trace_packet.get_return_value<GLint>();
5253 if (replay_result != trace_result)
5255 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5256 vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5262 case VOGL_ENTRYPOINT_glGetProgramivARB:
5264 if (!benchmark_mode())
5266 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5267 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5268 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5269 uint params_count = params_size / sizeof(GLint);
5271 int n = g_gl_enums.get_pname_count(pname);
5274 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5275 return cStatusSoftFailure;
5279 vogl::growable_array<GLint, 16> params(n + 1);
5280 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5282 GL_ENTRYPOINT(glGetProgramivARB)(
5283 trace_packet.get_param_value<GLenum>(0),
5287 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5289 if (params_count != static_cast<uint>(n))
5291 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5293 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5295 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));
5302 case VOGL_ENTRYPOINT_glGetProgramiv:
5304 if (!benchmark_mode())
5306 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5307 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5309 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5311 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5312 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5313 uint params_count = params_size / sizeof(GLint);
5315 int n = g_gl_enums.get_pname_count(pname);
5318 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5319 return cStatusSoftFailure;
5323 vogl::growable_array<GLint, 16> params(n + 1);
5324 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5326 GL_ENTRYPOINT(glGetProgramiv)(
5331 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5333 if (params_count != static_cast<uint>(n))
5335 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5337 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5339 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));
5346 case VOGL_ENTRYPOINT_glLinkProgram:
5347 case VOGL_ENTRYPOINT_glLinkProgramARB:
5348 case VOGL_ENTRYPOINT_glProgramBinary:
5350 handle_link_program(entrypoint_id);
5354 case VOGL_ENTRYPOINT_glCompileShader:
5356 GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5359 case VOGL_ENTRYPOINT_glCompileShaderARB:
5361 GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5364 case VOGL_ENTRYPOINT_glGetShaderiv:
5366 if (!benchmark_mode())
5368 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5369 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5371 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5374 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5376 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, ¶ms);
5378 if ((pClient_params) && (*pClient_params != params))
5380 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5381 vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5387 case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5389 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5390 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5392 GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5393 const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5394 VOGL_NOTE_UNUSED(pTrace_length);
5395 const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5396 VOGL_NOTE_UNUSED(pTrace_info_log);
5398 vogl::growable_array<GLchar, 512> log(trace_max_length);
5400 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5404 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());
5409 case VOGL_ENTRYPOINT_glGetBooleanv:
5411 if (!benchmark_mode())
5413 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5414 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5416 int n = g_gl_enums.get_pname_count(pname);
5419 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));
5420 return cStatusSoftFailure;
5424 vogl::growable_array<GLboolean, 16> params(n + 1);
5425 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5427 GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5429 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5431 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5433 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));
5440 case VOGL_ENTRYPOINT_glGetDoublev:
5442 if (!benchmark_mode())
5444 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5445 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5447 int n = g_gl_enums.get_pname_count(pname);
5450 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5451 return cStatusSoftFailure;
5455 vogl::growable_array<GLdouble, 17> params(n + 1);
5456 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5458 GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5460 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5462 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5464 process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5471 case VOGL_ENTRYPOINT_glGetFloatv:
5473 if (!benchmark_mode())
5475 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5476 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5477 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5479 int n = g_gl_enums.get_pname_count(pname);
5482 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5483 return cStatusSoftFailure;
5486 vogl::growable_array<GLfloat, 17> params(n + 1);
5487 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5489 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5491 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5493 if (static_cast<int>(trace_params_count) < n)
5494 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5495 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5497 process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5503 case VOGL_ENTRYPOINT_glGetIntegerv:
5505 if (!benchmark_mode())
5507 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5508 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5509 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5511 int n = g_gl_enums.get_pname_count(pname);
5514 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5515 return cStatusSoftFailure;
5518 vogl::growable_array<GLint, 16> params(n + 1);
5519 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5521 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5523 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5525 bool is_binding = false;
5528 case GL_ARRAY_BUFFER_BINDING:
5529 case GL_COLOR_ARRAY_BUFFER_BINDING:
5530 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5531 case GL_DRAW_FRAMEBUFFER_BINDING:
5532 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5533 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5534 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5535 case GL_INDEX_ARRAY_BUFFER_BINDING:
5536 case GL_NORMAL_ARRAY_BUFFER_BINDING:
5537 case GL_PIXEL_PACK_BUFFER_BINDING:
5538 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5539 case GL_PROGRAM_PIPELINE_BINDING:
5540 case GL_READ_FRAMEBUFFER_BINDING:
5541 case GL_RENDERBUFFER_BINDING:
5542 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5543 case GL_SHADER_STORAGE_BUFFER_BINDING:
5544 case GL_TEXTURE_BINDING_1D:
5545 case GL_TEXTURE_BINDING_1D_ARRAY:
5546 case GL_TEXTURE_BINDING_2D:
5547 case GL_TEXTURE_BINDING_2D_ARRAY:
5548 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5549 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5550 case GL_TEXTURE_BINDING_3D:
5551 case GL_TEXTURE_BINDING_BUFFER:
5552 case GL_TEXTURE_BINDING_CUBE_MAP:
5553 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5554 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5555 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5556 case GL_UNIFORM_BUFFER_BINDING:
5557 case GL_VERTEX_ARRAY_BINDING:
5558 case GL_VERTEX_ARRAY_BUFFER_BINDING:
5559 case GL_CURRENT_PROGRAM:
5568 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5571 if (static_cast<int>(trace_params_count) < n)
5573 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5575 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5577 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));
5578 for (int i = 0; i < n; i++)
5579 vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5586 // glProgramUniform's
5587 case VOGL_ENTRYPOINT_glProgramUniform1f:
5589 set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5592 case VOGL_ENTRYPOINT_glProgramUniform1i:
5594 set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5597 case VOGL_ENTRYPOINT_glProgramUniform1ui:
5599 set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5602 case VOGL_ENTRYPOINT_glProgramUniform2f:
5604 set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5607 case VOGL_ENTRYPOINT_glProgramUniform2i:
5609 set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5612 case VOGL_ENTRYPOINT_glProgramUniform2ui:
5614 set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5617 case VOGL_ENTRYPOINT_glProgramUniform3f:
5619 set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5622 case VOGL_ENTRYPOINT_glProgramUniform3i:
5624 set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5627 case VOGL_ENTRYPOINT_glProgramUniform3ui:
5629 set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5632 case VOGL_ENTRYPOINT_glProgramUniform4f:
5634 set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5637 case VOGL_ENTRYPOINT_glProgramUniform4i:
5639 set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5642 case VOGL_ENTRYPOINT_glProgramUniform4ui:
5644 set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5647 case VOGL_ENTRYPOINT_glProgramUniform1fv:
5649 set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5652 case VOGL_ENTRYPOINT_glProgramUniform2fv:
5654 set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5657 case VOGL_ENTRYPOINT_glProgramUniform3fv:
5659 set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5662 case VOGL_ENTRYPOINT_glProgramUniform4fv:
5664 set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5667 case VOGL_ENTRYPOINT_glProgramUniform1iv:
5669 set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5672 case VOGL_ENTRYPOINT_glProgramUniform2iv:
5674 set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5677 case VOGL_ENTRYPOINT_glProgramUniform3iv:
5679 set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5682 case VOGL_ENTRYPOINT_glProgramUniform4iv:
5684 set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5687 case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5689 set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5692 case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5694 set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5697 case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5699 set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5702 case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5704 set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5707 case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5709 set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5712 case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5714 set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5717 case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5719 set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5722 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5724 set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5727 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5729 set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5732 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5734 set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5737 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5739 set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5742 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5744 set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5747 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5749 set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5753 case VOGL_ENTRYPOINT_glUniform1f:
5755 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5758 case VOGL_ENTRYPOINT_glUniform1fARB:
5760 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5763 case VOGL_ENTRYPOINT_glUniform2f:
5765 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5768 case VOGL_ENTRYPOINT_glUniform2fARB:
5770 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5773 case VOGL_ENTRYPOINT_glUniform3f:
5775 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5778 case VOGL_ENTRYPOINT_glUniform3fARB:
5780 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5783 case VOGL_ENTRYPOINT_glUniform4f:
5785 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5788 case VOGL_ENTRYPOINT_glUniform4fARB:
5790 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5793 case VOGL_ENTRYPOINT_glUniform1i:
5795 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5798 case VOGL_ENTRYPOINT_glUniform1iARB:
5800 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5803 case VOGL_ENTRYPOINT_glUniform2i:
5805 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5808 case VOGL_ENTRYPOINT_glUniform2iARB:
5810 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5813 case VOGL_ENTRYPOINT_glUniform3i:
5815 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5818 case VOGL_ENTRYPOINT_glUniform3iARB:
5820 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5823 case VOGL_ENTRYPOINT_glUniform4i:
5825 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5828 case VOGL_ENTRYPOINT_glUniform4iARB:
5830 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5833 case VOGL_ENTRYPOINT_glUniform1ui:
5835 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5838 case VOGL_ENTRYPOINT_glUniform1uiEXT:
5840 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5843 case VOGL_ENTRYPOINT_glUniform2ui:
5845 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5848 case VOGL_ENTRYPOINT_glUniform2uiEXT:
5850 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5853 case VOGL_ENTRYPOINT_glUniform3ui:
5855 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5858 case VOGL_ENTRYPOINT_glUniform3uiEXT:
5860 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5863 case VOGL_ENTRYPOINT_glUniform4ui:
5865 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5868 case VOGL_ENTRYPOINT_glUniform4uiEXT:
5870 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5873 case VOGL_ENTRYPOINT_glUniform1uiv:
5875 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5878 case VOGL_ENTRYPOINT_glUniform1uivEXT:
5880 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5883 case VOGL_ENTRYPOINT_glUniform2uiv:
5885 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5888 case VOGL_ENTRYPOINT_glUniform2uivEXT:
5890 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5893 case VOGL_ENTRYPOINT_glUniform3uiv:
5895 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5898 case VOGL_ENTRYPOINT_glUniform3uivEXT:
5900 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5903 case VOGL_ENTRYPOINT_glUniform4uiv:
5905 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5908 case VOGL_ENTRYPOINT_glUniform4uivEXT:
5910 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5913 case VOGL_ENTRYPOINT_glUniform1iv:
5915 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5918 case VOGL_ENTRYPOINT_glUniform1ivARB:
5920 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5923 case VOGL_ENTRYPOINT_glUniform2iv:
5925 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5928 case VOGL_ENTRYPOINT_glUniform2ivARB:
5930 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5933 case VOGL_ENTRYPOINT_glUniform3iv:
5935 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5938 case VOGL_ENTRYPOINT_glUniform3ivARB:
5940 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5943 case VOGL_ENTRYPOINT_glUniform4iv:
5945 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5948 case VOGL_ENTRYPOINT_glUniform4ivARB:
5950 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5953 case VOGL_ENTRYPOINT_glUniform1fv:
5955 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5958 case VOGL_ENTRYPOINT_glUniform1fvARB:
5960 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5963 case VOGL_ENTRYPOINT_glUniform2fv:
5965 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5968 case VOGL_ENTRYPOINT_glUniform2fvARB:
5970 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
5973 case VOGL_ENTRYPOINT_glUniform3fv:
5975 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
5978 case VOGL_ENTRYPOINT_glUniform3fvARB:
5980 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
5983 case VOGL_ENTRYPOINT_glUniform4fv:
5985 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
5988 case VOGL_ENTRYPOINT_glUniform4fvARB:
5990 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
5993 case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
5995 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
5998 case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6000 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6003 case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6005 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6008 case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6010 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6013 case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6015 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6018 case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6020 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6023 case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6025 set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6028 case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6030 set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6033 case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6035 set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6038 case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6040 set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6043 case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6045 set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6048 case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6050 set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6053 case VOGL_ENTRYPOINT_glBeginQuery:
6054 case VOGL_ENTRYPOINT_glBeginQueryARB:
6056 GLenum target = trace_packet.get_param_value<GLenum>(0);
6057 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6058 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6060 if (!m_pCur_context_state->m_inside_gl_begin)
6063 if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6064 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6066 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6068 if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6070 if (check_gl_error())
6071 return cStatusGLError;
6073 get_shared_state()->m_query_targets[replay_handle] = target;
6078 case VOGL_ENTRYPOINT_glEndQuery:
6080 GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6083 case VOGL_ENTRYPOINT_glEndQueryARB:
6085 GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6088 case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6090 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6091 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6093 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6095 int n = g_gl_enums.get_pname_count(pname);
6098 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6099 return cStatusSoftFailure;
6103 vogl::growable_array<GLint, 16> params(n + 1);
6104 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6106 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6108 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6113 case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6115 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6116 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6118 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6120 int n = g_gl_enums.get_pname_count(pname);
6123 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6124 return cStatusSoftFailure;
6128 vogl::growable_array<GLint, 16> params(n + 1);
6129 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6131 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6133 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6138 case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6140 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6141 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6143 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6145 int n = g_gl_enums.get_pname_count(pname);
6148 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6149 return cStatusSoftFailure;
6153 vogl::growable_array<GLuint, 16> params(n + 1);
6154 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6156 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6158 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6163 case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6165 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6166 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6168 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6170 int n = g_gl_enums.get_pname_count(pname);
6173 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6174 return cStatusSoftFailure;
6178 vogl::growable_array<GLuint, 16> params(n + 1);
6179 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6181 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6183 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6188 case VOGL_ENTRYPOINT_glQueryCounter:
6190 VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6192 id = map_handle(get_shared_state()->m_queries, id);
6194 VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6198 case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6200 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6201 VOGL_NOTE_UNUSED(pTrace_params);
6203 id = map_handle(get_shared_state()->m_queries, id);
6205 int n = g_gl_enums.get_pname_count(pname);
6208 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6209 return cStatusSoftFailure;
6212 vogl::growable_array<GLint64, 16> temp_params(n + 1);
6213 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6215 GLint64 *pReplay_params = temp_params.get_ptr();
6217 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6219 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6223 case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6225 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6226 VOGL_NOTE_UNUSED(pTrace_params);
6228 id = map_handle(get_shared_state()->m_queries, id);
6230 int n = g_gl_enums.get_pname_count(pname);
6233 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6234 return cStatusSoftFailure;
6237 vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6238 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6240 GLuint64 *pReplay_params = temp_params.get_ptr();
6242 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6244 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6248 case VOGL_ENTRYPOINT_glBindBuffer:
6249 case VOGL_ENTRYPOINT_glBindBufferARB:
6251 GLenum target = trace_packet.get_param_value<GLenum>(0);
6252 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6253 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6257 SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6259 if (check_gl_error())
6260 return cStatusGLError;
6262 if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6264 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6266 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6267 else if (*pBinding == GL_NONE)
6273 case VOGL_ENTRYPOINT_glBindBufferBase:
6274 case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6275 case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6277 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6279 GLuint trace_buffer = buffer;
6280 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6284 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6285 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6286 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6287 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6289 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6291 if (check_gl_error())
6292 return cStatusGLError;
6294 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6296 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6298 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6299 else if (*pBinding == GL_NONE)
6305 case VOGL_ENTRYPOINT_glBindBufferRange:
6306 case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6307 case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6309 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6311 GLuint trace_buffer = buffer;
6312 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6316 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6317 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6318 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6319 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6321 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6323 if (check_gl_error())
6324 return cStatusGLError;
6326 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6328 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6330 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6331 else if (*pBinding == GL_NONE)
6337 case VOGL_ENTRYPOINT_glFenceSync:
6339 vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6342 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6345 process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6346 return cStatusHardFailure;
6350 get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6356 case VOGL_ENTRYPOINT_glWaitSync:
6357 case VOGL_ENTRYPOINT_glClientWaitSync:
6359 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6360 GLsync replay_sync = NULL;
6362 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6363 if (it == get_shared_state()->m_syncs.end())
6367 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6368 return cStatusHardFailure;
6373 replay_sync = it->second;
6376 if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6377 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6379 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6383 case VOGL_ENTRYPOINT_glDeleteSync:
6385 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6386 GLsync replay_sync = NULL;
6388 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6389 if (it == get_shared_state()->m_syncs.end())
6393 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6394 return cStatusHardFailure;
6399 replay_sync = it->second;
6402 GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6406 get_shared_state()->m_syncs.erase(trace_sync);
6411 case VOGL_ENTRYPOINT_glVertexPointer:
6413 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),
6414 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6417 case VOGL_ENTRYPOINT_glVertexPointerEXT:
6419 VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6420 VOGL_NOTE_UNUSED(pTrace_pointer);
6422 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]);
6425 case VOGL_ENTRYPOINT_glColorPointer:
6427 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),
6428 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6431 case VOGL_ENTRYPOINT_glColorPointerEXT:
6433 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6434 VOGL_NOTE_UNUSED(pTrace_pointer);
6436 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]);
6439 case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6441 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),
6442 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6445 case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6447 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),
6448 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6451 case VOGL_ENTRYPOINT_glTexCoordPointer:
6453 GLint cur_client_active_texture = 0;
6454 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6456 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6457 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6459 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);
6460 return cStatusSoftFailure;
6463 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),
6464 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6467 case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6469 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6470 VOGL_NOTE_UNUSED(pTrace_pointer);
6472 GLint cur_client_active_texture = 0;
6473 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6475 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6476 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6478 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);
6479 return cStatusSoftFailure;
6482 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]);
6485 case VOGL_ENTRYPOINT_glFogCoordPointer:
6487 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),
6488 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6491 case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6493 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),
6494 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6497 case VOGL_ENTRYPOINT_glIndexPointer:
6499 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),
6500 vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6503 case VOGL_ENTRYPOINT_glIndexPointerEXT:
6505 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6506 VOGL_NOTE_UNUSED(pTrace_pointer);
6508 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6511 case VOGL_ENTRYPOINT_glNormalPointer:
6513 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),
6514 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6517 case VOGL_ENTRYPOINT_glNormalPointerEXT:
6519 VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6520 VOGL_NOTE_UNUSED(pTrace_pointer);
6522 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6525 case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6527 vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6528 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6531 case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6533 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6534 VOGL_NOTE_UNUSED(pTrace_pointer);
6536 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));
6539 case VOGL_ENTRYPOINT_glInterleavedArrays:
6541 // TODO: Test this more!
6542 GLenum format = trace_packet.get_param_value<GLenum>(0);
6543 GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6544 const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6547 for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6548 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6550 if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6552 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6553 return cStatusSoftFailure;
6558 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6559 return cStatusSoftFailure;
6562 const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6567 VOGL_ASSERT(stride > 0);
6570 GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6571 GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6572 GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6573 GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6579 GLint cur_client_active_texture = 0;
6580 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6582 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6583 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6585 process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6586 return cStatusSoftFailure;
6589 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6590 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6591 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6595 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6602 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6603 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6604 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6608 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6615 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6616 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6617 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6621 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6626 GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6627 vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6628 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6632 case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6633 case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6635 GLuint index = trace_packet.get_param_value<GLuint>(0);
6636 GLint size = trace_packet.get_param_value<GLint>(1);
6637 GLenum type = trace_packet.get_param_value<GLenum>(2);
6638 GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6639 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6641 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6643 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6644 return cStatusSoftFailure;
6647 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6648 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6649 if ((!buffer) && (trace_pointer))
6651 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6652 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6653 if (!m_client_side_vertex_attrib_data[index].size())
6655 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6657 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6660 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6661 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6663 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6667 case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6668 case VOGL_ENTRYPOINT_glVertexAttribPointer:
6670 GLuint index = trace_packet.get_param_value<GLuint>(0);
6671 GLint size = trace_packet.get_param_value<GLint>(1);
6672 GLenum type = trace_packet.get_param_value<GLenum>(2);
6673 GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6674 GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6675 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6677 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6679 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6680 return cStatusSoftFailure;
6683 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6684 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6685 if ((!buffer) && (trace_pointer))
6687 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6688 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6689 if (!m_client_side_vertex_attrib_data[index].size())
6691 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6693 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6696 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6697 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6699 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6703 case VOGL_ENTRYPOINT_glDrawRangeElements:
6704 case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6706 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6707 GLuint start = trace_packet.get_param_value<GLuint>(1);
6708 GLuint end = trace_packet.get_param_value<GLuint>(2);
6709 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6710 GLenum type = trace_packet.get_param_value<GLenum>(4);
6711 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6713 const GLvoid *pIndices;
6714 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6715 return cStatusSoftFailure;
6717 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6719 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6720 GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6722 GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6727 case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6729 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6730 GLuint start = trace_packet.get_param_value<GLuint>(1);
6731 GLuint end = trace_packet.get_param_value<GLuint>(2);
6732 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6733 GLenum type = trace_packet.get_param_value<GLenum>(4);
6734 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6735 GLint basevertex = trace_packet.get_param_value<GLint>(6);
6737 const GLvoid *pIndices;
6738 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6739 return cStatusSoftFailure;
6741 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6743 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6748 case VOGL_ENTRYPOINT_glDrawElements:
6750 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6751 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6752 GLenum type = trace_packet.get_param_value<GLenum>(2);
6753 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6755 const GLvoid *pIndices;
6756 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6757 return cStatusSoftFailure;
6759 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6761 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6766 case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6767 case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6769 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6771 const GLvoid *pIndices = NULL;
6772 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6773 return cStatusSoftFailure;
6775 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6777 GLsizei start = first, primcount = instancecount;
6778 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6781 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6785 case VOGL_ENTRYPOINT_glDrawArrays:
6786 case VOGL_ENTRYPOINT_glDrawArraysEXT:
6788 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6789 GLint first = trace_packet.get_param_value<GLint>(1);
6790 GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6792 const GLvoid *pIndices = NULL;
6793 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6794 return cStatusSoftFailure;
6796 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6798 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6799 GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6801 GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6806 case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6807 case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6808 case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6810 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6811 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6812 GLenum type = trace_packet.get_param_value<GLenum>(2);
6813 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6814 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6816 const GLvoid *pIndices;
6817 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6818 return cStatusSoftFailure;
6820 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6822 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6823 GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6824 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6825 GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6827 GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6832 case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6834 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6835 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6836 GLenum type = trace_packet.get_param_value<GLenum>(2);
6837 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6838 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6839 GLint basevertex = trace_packet.get_param_value<GLint>(5);
6841 const GLvoid *pIndices;
6842 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6843 return cStatusSoftFailure;
6845 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6847 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6852 case VOGL_ENTRYPOINT_glMultiDrawArrays:
6853 case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6855 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6857 const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6858 uint first_size = trace_packet.get_param_client_memory_data_size(1);
6860 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6861 uint count_size = trace_packet.get_param_client_memory_data_size(2);
6863 GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6865 if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6867 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6868 return cStatusSoftFailure;
6871 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6873 // Multi-draws with client side arrays are not supported for replay.
6874 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6875 GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6877 GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6882 case VOGL_ENTRYPOINT_glMultiDrawElements:
6883 case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6885 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6887 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6888 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6890 GLenum type = trace_packet.get_param_value<GLenum>(2);
6892 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6894 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6896 if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6898 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6899 return cStatusSoftFailure;
6902 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6903 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6904 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6906 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6908 // Multi-draws with client side arrays are not supported for replay.
6909 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6910 GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6912 GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6917 case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6919 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6921 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6922 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6924 GLenum type = trace_packet.get_param_value<GLenum>(2);
6926 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6927 //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6928 //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6930 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6932 const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6933 uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6935 if ((count_size != primcount * sizeof(GLsizei)) ||
6936 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6937 (base_vertex_size != primcount * sizeof(GLint)))
6939 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);
6940 return cStatusSoftFailure;
6943 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6944 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6945 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6947 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6949 // Multi-draws with client side arrays are not supported for replay.
6950 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6955 case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6957 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6958 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6959 GLenum type = trace_packet.get_param_value<GLenum>(2);
6960 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6961 GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6963 const GLvoid *pIndices;
6964 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6965 return cStatusSoftFailure;
6967 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6969 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
6974 case VOGL_ENTRYPOINT_glGetBufferSubData:
6976 if (!benchmark_mode())
6978 GLenum target = trace_packet.get_param_value<GLenum>(0);
6979 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
6980 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
6981 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
6983 if (offset != static_cast<uintptr_t>(offset))
6985 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
6986 return cStatusHardFailure;
6989 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
6991 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
6992 return cStatusHardFailure;
6995 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
6997 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
6999 if ((buf.size()) && (pTrace_ptr))
7001 if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7003 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7010 case VOGL_ENTRYPOINT_glGetClipPlane:
7012 if (!benchmark_mode())
7014 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7015 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7017 GLdouble equation[4];
7018 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7020 if (pTrace_equation)
7022 if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7024 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7031 case VOGL_ENTRYPOINT_glBufferData:
7032 case VOGL_ENTRYPOINT_glBufferDataARB:
7034 GLenum target = trace_packet.get_param_value<GLenum>(0);
7035 vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7036 const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7037 uint data_size = trace_packet.get_param_client_memory_data_size(2);
7038 GLenum usage = trace_packet.get_param_value<GLenum>(3);
7040 if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7042 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7043 return cStatusHardFailure;
7046 if (size != static_cast<uintptr_t>(size))
7048 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7049 return cStatusHardFailure;
7052 if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7053 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7055 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7057 GLuint buffer = vogl_get_bound_gl_buffer(target);
7060 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7063 for (i = 0; i < mapped_bufs.size(); i++)
7065 if (mapped_bufs[i].m_buffer == buffer)
7067 process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7069 mapped_bufs.erase_unordered(i);
7077 case VOGL_ENTRYPOINT_glMapBufferARB:
7078 case VOGL_ENTRYPOINT_glMapBuffer:
7080 GLenum target = trace_packet.get_param_value<GLenum>(0);
7081 GLenum access = trace_packet.get_param_value<GLenum>(1);
7082 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7084 // FIXME - must call GL even if !pTrace_result
7085 if (trace_result_ptr_value)
7088 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7089 pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7091 pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7095 process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7096 return cStatusHardFailure;
7099 GLuint buffer = vogl_get_bound_gl_buffer(target);
7101 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7104 for (i = 0; i < mapped_bufs.size(); i++)
7106 if (mapped_bufs[i].m_buffer == buffer)
7108 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7109 return cStatusHardFailure;
7113 if (i == mapped_bufs.size())
7116 GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7118 vogl_mapped_buffer_desc m;
7119 m.m_buffer = buffer;
7120 m.m_target = target;
7122 m.m_length = length;
7123 m.m_access = access;
7126 mapped_bufs.push_back(m);
7132 case VOGL_ENTRYPOINT_glMapBufferRange:
7134 GLenum target = trace_packet.get_param_value<GLenum>(0);
7135 vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7136 vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7137 GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7138 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7140 if (offset != static_cast<uintptr_t>(offset))
7142 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7143 return cStatusHardFailure;
7145 if (length != static_cast<uintptr_t>(length))
7147 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7148 return cStatusHardFailure;
7151 // FIXME - must call GL even if !pTrace_result
7152 if (trace_result_ptr_value)
7154 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7157 process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7158 return cStatusHardFailure;
7161 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7163 GLuint buffer = vogl_get_bound_gl_buffer(target);
7165 for (i = 0; i < mapped_bufs.size(); i++)
7167 if (mapped_bufs[i].m_buffer == buffer)
7169 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7170 return cStatusHardFailure;
7174 if (i == mapped_bufs.size())
7176 vogl_mapped_buffer_desc m;
7177 m.m_buffer = buffer;
7178 m.m_target = target;
7179 m.m_offset = offset;
7180 m.m_length = length;
7181 m.m_access = access;
7184 mapped_bufs.push_back(m);
7190 case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7192 // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7195 case VOGL_ENTRYPOINT_glUnmapBufferARB:
7196 case VOGL_ENTRYPOINT_glUnmapBuffer:
7198 GLenum target = trace_packet.get_param_value<GLenum>(0);
7199 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7201 GLuint buffer = vogl_get_bound_gl_buffer(target);
7203 // FIXME - must call GL even if !buffer
7206 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7208 uint mapped_buffers_index;
7209 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7210 if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7212 if (mapped_buffers_index == mapped_bufs.size())
7214 process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7215 return cStatusHardFailure;
7218 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7220 bool writable_map = false;
7221 bool explicit_bit = false;
7222 if (map_desc.m_range)
7224 writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7225 explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7229 writable_map = (map_desc.m_access != GL_READ_ONLY);
7234 const key_value_map &unmap_data = trace_packet.get_key_value_map();
7238 int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7240 for (int i = 0; i < num_flushed_ranges; i++)
7242 int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7243 int64_t size = unmap_data.get_int64(i * 4 + 1);
7244 VOGL_NOTE_UNUSED(size);
7245 const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7248 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7249 return cStatusHardFailure;
7252 if (ofs != static_cast<GLintptr>(ofs))
7254 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7255 return cStatusHardFailure;
7258 VOGL_ASSERT(size == pData->size());
7260 memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7262 GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7267 int64_t ofs = unmap_data.get_int64(0);
7268 VOGL_NOTE_UNUSED(ofs);
7269 int64_t size = unmap_data.get_int64(1);
7270 VOGL_NOTE_UNUSED(size);
7271 const uint8_vec *pData = unmap_data.get_blob(2);
7274 process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7275 return cStatusHardFailure;
7279 memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7284 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7287 GLboolean replay_result;
7288 if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7289 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7291 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7293 if (trace_result != replay_result)
7294 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);
7298 case VOGL_ENTRYPOINT_glGenVertexArrays:
7300 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))
7301 return cStatusHardFailure;
7304 case VOGL_ENTRYPOINT_glBindVertexArray:
7306 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7307 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7309 GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7312 case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7314 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));
7317 case VOGL_ENTRYPOINT_glIsFramebuffer:
7318 case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7320 if (!benchmark_mode())
7322 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7323 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7324 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7326 GLboolean replay_result;
7327 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7328 replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7330 replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7332 if (trace_result != replay_result)
7333 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));
7338 case VOGL_ENTRYPOINT_glIsBuffer:
7340 if (!benchmark_mode())
7342 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7343 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7344 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7346 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7347 if (trace_result != replay_result)
7348 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));
7352 case VOGL_ENTRYPOINT_glIsEnabledi:
7354 if (!benchmark_mode())
7356 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7357 GLuint index = trace_packet.get_param_value<GLuint>(1);
7358 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7360 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7361 if (trace_result != replay_result)
7362 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));
7366 case VOGL_ENTRYPOINT_glIsEnabled:
7368 if (!benchmark_mode())
7370 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7371 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7373 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7374 if (trace_result != replay_result)
7375 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));
7379 case VOGL_ENTRYPOINT_glIsProgram:
7381 if (!benchmark_mode())
7383 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7384 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7385 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7387 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7389 if (trace_result != replay_result)
7390 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));
7394 case VOGL_ENTRYPOINT_glIsQuery:
7396 if (!benchmark_mode())
7398 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7399 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7400 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7402 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7403 if (trace_result != replay_result)
7404 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));
7408 case VOGL_ENTRYPOINT_glIsShader:
7410 if (!benchmark_mode())
7412 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7413 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7414 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7416 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7417 if (trace_result != replay_result)
7418 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));
7422 case VOGL_ENTRYPOINT_glIsTexture:
7423 case VOGL_ENTRYPOINT_glIsTextureEXT:
7425 if (!benchmark_mode())
7427 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7428 GLuint replay_handle = trace_handle;
7429 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7431 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7433 GLboolean replay_result;
7434 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7435 replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7437 replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7439 if (trace_result != replay_result)
7440 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));
7445 case VOGL_ENTRYPOINT_glIsVertexArray:
7447 if (!benchmark_mode())
7449 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7450 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7451 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7453 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7454 if (trace_result != replay_result)
7455 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));
7460 case VOGL_ENTRYPOINT_glReadPixels:
7462 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7464 if (!benchmark_mode())
7466 GLint x = trace_packet.get_param_value<GLint>(0);
7467 GLint y = trace_packet.get_param_value<GLint>(1);
7468 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7469 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7470 GLenum format = trace_packet.get_param_value<GLenum>(4);
7471 GLenum type = trace_packet.get_param_value<GLenum>(5);
7472 const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7473 uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7475 size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7476 if (replay_data_size != trace_data_size)
7478 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7480 else if (!trace_data)
7482 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7485 if (replay_data_size > cUINT32_MAX)
7487 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7488 return cStatusHardFailure;
7491 vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7492 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7494 if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7496 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7498 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7505 case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7507 if (!benchmark_mode())
7509 GLenum target = trace_packet.get_param_value<GLenum>(0);
7510 GLint level = trace_packet.get_param_value<GLint>(1);
7511 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7512 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7513 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7515 int n = g_gl_enums.get_pname_count(pname);
7518 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7519 return cStatusSoftFailure;
7522 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7523 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7525 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7527 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7530 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7531 else if (trace_params_size != sizeof(GLfloat) * n)
7532 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7533 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7534 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7539 case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7541 if (!benchmark_mode())
7543 GLenum target = trace_packet.get_param_value<GLenum>(0);
7544 GLint level = trace_packet.get_param_value<GLint>(1);
7545 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7546 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7547 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7549 int n = g_gl_enums.get_pname_count(pname);
7552 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7553 return cStatusSoftFailure;
7556 vogl::growable_array<GLint, 16> replay_params(n + 1);
7557 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7559 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7561 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7564 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7565 else if (trace_params_size != sizeof(GLint) * n)
7566 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7567 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7568 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7573 case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7574 case VOGL_ENTRYPOINT_glGetTexParameteriv:
7576 if (!benchmark_mode())
7578 GLenum target = trace_packet.get_param_value<GLenum>(0);
7579 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7580 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7581 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7583 int n = g_gl_enums.get_pname_count(pname);
7586 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7587 return cStatusSoftFailure;
7590 vogl::growable_array<GLint, 16> replay_params(n + 1);
7591 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7593 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7594 GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7596 GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7598 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7601 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7602 else if (trace_params_size != sizeof(GLint) * n)
7603 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7604 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7605 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7610 case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7612 if (!benchmark_mode())
7614 GLenum target = trace_packet.get_param_value<GLenum>(0);
7615 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7616 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7617 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7619 int n = g_gl_enums.get_pname_count(pname);
7622 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7623 return cStatusSoftFailure;
7626 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7627 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7629 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7631 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7634 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7635 else if (trace_params_size != sizeof(GLuint) * n)
7636 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7637 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7638 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7643 case VOGL_ENTRYPOINT_glGetTexParameterfv:
7645 if (!benchmark_mode())
7647 GLenum target = trace_packet.get_param_value<GLenum>(0);
7648 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7649 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7650 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7652 int n = g_gl_enums.get_pname_count(pname);
7655 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7656 return cStatusSoftFailure;
7659 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7660 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7662 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7664 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7667 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7668 else if (trace_params_size != sizeof(GLfloat) * n)
7669 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7670 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7671 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7677 case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7679 status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7680 if (status != cStatusOK)
7684 case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7686 status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7687 if (status != cStatusOK)
7691 case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7693 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7694 if (status != cStatusOK)
7698 case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7700 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7701 if (status != cStatusOK)
7705 case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7707 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7708 if (status != cStatusOK)
7712 case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7714 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7715 if (status != cStatusOK)
7719 case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7721 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7722 if (status != cStatusOK)
7726 case VOGL_ENTRYPOINT_glGenLists:
7728 GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7729 GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7731 if (trace_base_handle)
7735 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7737 if ((check_gl_error()) || (!replay_base_handle))
7739 process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7740 return cStatusHardFailure;
7743 for (GLsizei i = 0; i < range; i++)
7745 GLuint trace_handle = trace_base_handle + i;
7746 GLuint replay_handle = replay_base_handle + i;
7748 if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7749 return cStatusHardFailure;
7751 if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7753 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);
7759 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7760 if (replay_base_handle)
7762 process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7764 GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7770 case VOGL_ENTRYPOINT_glCallList:
7772 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7773 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7775 GL_ENTRYPOINT(glCallList)(replay_handle);
7777 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7779 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7782 if ((status = post_draw_call()) != cStatusOK)
7787 case VOGL_ENTRYPOINT_glCallLists:
7789 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7790 GLenum type = trace_packet.get_param_value<GLenum>(1);
7791 const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7792 uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7794 uint type_size = vogl_get_gl_type_size(type);
7797 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7798 return cStatusSoftFailure;
7801 if ((n) && (!pTrace_lists))
7803 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7804 return cStatusSoftFailure;
7807 if (trace_lists_size < (type_size * n))
7809 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7810 return cStatusSoftFailure;
7813 GLuint list_base = 0;
7814 GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7816 const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7817 for (GLsizei i = 0; i < n; i++)
7819 GLint trace_handle = list_base;
7824 trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7828 case GL_UNSIGNED_BYTE:
7830 trace_handle += *pTrace_lists_ptr;
7836 trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7837 pTrace_lists_ptr += sizeof(int16);
7840 case GL_UNSIGNED_SHORT:
7842 trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7843 pTrace_lists_ptr += sizeof(uint16);
7848 trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7849 pTrace_lists_ptr += sizeof(int32);
7852 case GL_UNSIGNED_INT:
7854 trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7855 pTrace_lists_ptr += sizeof(uint32);
7860 trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7861 pTrace_lists_ptr += sizeof(float);
7866 trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7867 pTrace_lists_ptr += 2;
7872 trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7873 pTrace_lists_ptr += 3;
7878 trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7879 pTrace_lists_ptr += 4;
7884 process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7885 return cStatusSoftFailure;
7889 if (trace_handle <= 0)
7891 process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7895 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7896 GL_ENTRYPOINT(glCallList)(replay_handle);
7898 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7900 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7905 if ((status = post_draw_call()) != cStatusOK)
7910 case VOGL_ENTRYPOINT_glDeleteLists:
7912 GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7913 GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7915 for (GLsizei i = 0; i < range; i++)
7917 GLuint trace_handle = trace_list + i;
7918 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7920 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7922 process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7928 case VOGL_ENTRYPOINT_glIsList:
7930 if (!benchmark_mode())
7932 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7933 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7934 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7936 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7937 if (trace_result != replay_result)
7938 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));
7943 case VOGL_ENTRYPOINT_glNewList:
7945 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7946 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7947 GLenum mode = trace_packet.get_param_value<GLenum>(1);
7951 GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7953 if (!check_gl_error())
7955 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7957 get_context_state()->m_current_display_list_mode = mode;
7958 get_context_state()->m_current_display_list_handle = trace_handle;
7961 // TODO: Check if glNewList() failed vs the replay.
7962 // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7963 // 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.
7966 case VOGL_ENTRYPOINT_glListBase:
7968 GLuint base = trace_packet.get_param_value<GLuint>(0);
7969 GL_ENTRYPOINT(glListBase)(base);
7972 case VOGL_ENTRYPOINT_glEndList:
7974 GL_ENTRYPOINT(glEndList)();
7976 if (!get_context_state()->is_composing_display_list())
7978 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7982 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7983 process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7985 get_context_state()->m_current_display_list_mode = GL_NONE;
7986 get_context_state()->m_current_display_list_handle = -1;
7991 case VOGL_ENTRYPOINT_glFeedbackBuffer:
7993 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7994 GLenum type = trace_packet.get_param_value<GLenum>(1);
7996 if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
7997 m_pCur_context_state->m_feedback_buffer.resize(size);
7999 GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
8003 case VOGL_ENTRYPOINT_glSeparableFilter2D:
8005 GLenum target = trace_packet.get_param_value<GLenum>(0);
8006 GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
8007 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8008 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8009 GLenum format = trace_packet.get_param_value<GLenum>(4);
8010 GLenum type = trace_packet.get_param_value<GLenum>(5);
8012 const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
8013 uint row_size = trace_packet.get_param_client_memory_data_size(6);
8014 if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8016 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8017 return cStatusSoftFailure;
8020 const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8021 uint col_size = trace_packet.get_param_client_memory_data_size(7);
8022 if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8024 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8025 return cStatusSoftFailure;
8028 GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8032 case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8034 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8035 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8037 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));
8041 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8043 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8044 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8046 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));
8049 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8051 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8052 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8054 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));
8058 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8060 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8061 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8063 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));
8066 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8068 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8069 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8071 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8072 trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8073 trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8076 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8078 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8079 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8081 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));
8084 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8086 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8087 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8089 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));
8092 case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8094 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8095 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8097 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));
8100 case VOGL_ENTRYPOINT_glGetTexEnvfv:
8102 if (!benchmark_mode())
8104 GLenum target = trace_packet.get_param_value<GLenum>(0);
8105 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8106 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8108 GLfloat vals[4] = { 0, 0, 0, 0 };
8110 int n = g_gl_enums.get_pname_count(pname);
8111 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8113 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8117 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8119 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8121 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8127 case VOGL_ENTRYPOINT_glGetTexEnviv:
8129 if (!benchmark_mode())
8131 GLenum target = trace_packet.get_param_value<GLenum>(0);
8132 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8133 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8135 GLint vals[4] = { 0, 0, 0, 0 };
8137 int n = g_gl_enums.get_pname_count(pname);
8138 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8140 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8144 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8146 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8148 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8154 case VOGL_ENTRYPOINT_glGetTexGendv:
8156 if (!benchmark_mode())
8158 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8159 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8160 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8162 GLdouble vals[4] = { 0, 0, 0, 0 };
8164 int n = g_gl_enums.get_pname_count(pname);
8165 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8167 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8171 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8173 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8175 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8181 case VOGL_ENTRYPOINT_glGetTexGenfv:
8183 if (!benchmark_mode())
8185 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8186 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8187 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8189 GLfloat vals[4] = { 0, 0, 0, 0 };
8191 int n = g_gl_enums.get_pname_count(pname);
8192 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8194 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8198 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8200 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8202 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8208 case VOGL_ENTRYPOINT_glGetTexGeniv:
8210 if (!benchmark_mode())
8212 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8213 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8214 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8216 GLint vals[4] = { 0, 0, 0, 0 };
8218 int n = g_gl_enums.get_pname_count(pname);
8219 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8221 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8225 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8227 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8229 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8235 case VOGL_ENTRYPOINT_glGetLightfv:
8237 if (!benchmark_mode())
8239 GLenum light = trace_packet.get_param_value<GLenum>(0);
8240 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8241 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8243 GLfloat vals[4] = { 0, 0, 0, 0 };
8245 int n = g_gl_enums.get_pname_count(pname);
8246 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8248 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8252 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8254 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8256 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8262 case VOGL_ENTRYPOINT_glGetLightiv:
8264 if (!benchmark_mode())
8266 GLenum light = trace_packet.get_param_value<GLenum>(0);
8267 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8268 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8270 GLint vals[4] = { 0, 0, 0, 0 };
8272 int n = g_gl_enums.get_pname_count(pname);
8273 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8275 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8279 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8281 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8283 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8289 case VOGL_ENTRYPOINT_glSelectBuffer:
8291 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8293 if (m_pCur_context_state->m_select_buffer.try_resize(size))
8295 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8299 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8304 case VOGL_ENTRYPOINT_glClearBufferfv:
8306 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8308 // TODO: Check params
8310 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8314 case VOGL_ENTRYPOINT_glClearBufferiv:
8316 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8318 // TODO: Check params
8320 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8324 case VOGL_ENTRYPOINT_glClearBufferuiv:
8326 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8328 // TODO: Check params
8330 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8334 case VOGL_ENTRYPOINT_glTexBuffer:
8335 case VOGL_ENTRYPOINT_glTexBufferARB:
8336 case VOGL_ENTRYPOINT_glTexBufferEXT:
8338 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8340 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8342 SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8345 case VOGL_ENTRYPOINT_glBeginConditionalRender:
8347 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8349 id = map_handle(get_shared_state()->m_queries, id);
8351 VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8354 case VOGL_ENTRYPOINT_glEndConditionalRender:
8356 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8358 VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8361 case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8363 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8365 VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8368 case VOGL_ENTRYPOINT_glEndTransformFeedback:
8370 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8372 VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8376 case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8378 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8379 VOGL_NOTE_UNUSED(pTrace_varyings);
8381 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8383 dynamic_string_array replay_varyings(count);
8385 const key_value_map &key_value_map = trace_packet.get_key_value_map();
8386 const value_to_value_hash_map &hash_map = key_value_map.get_map();
8388 for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8390 int key_index = it->first.get_int();
8392 if ((key_index >= 0) && (key_index < count))
8394 const dynamic_string *pName = it->second.get_string_ptr();
8397 replay_varyings[key_index] = pName ? *pName : "";
8405 vogl::vector<const GLchar *> str_ptrs(count);
8406 for (int i = 0; i < count; i++)
8407 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8409 GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8411 VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8415 case VOGL_ENTRYPOINT_glUniformBufferEXT:
8417 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8419 GLuint trace_program = program;
8421 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8422 location = determine_uniform_replay_location(trace_program, location);
8423 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8425 VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8428 case VOGL_ENTRYPOINT_glUniformBlockBinding:
8430 // TODO: Does any of this other stuff need to be remapped?
8431 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8433 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8435 VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8438 case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8440 // TODO - we need to hook up this extension to the tracer
8443 case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8445 // TODO - we need to hook up this extension to the tracer
8448 case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8449 case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8450 case VOGL_ENTRYPOINT_glDebugMessageControlARB:
8451 case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8456 case VOGL_ENTRYPOINT_glBitmap:
8458 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8460 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8462 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8463 pTrace_bitmap = (const GLubyte *)ptr_val;
8466 VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8470 case VOGL_ENTRYPOINT_glColorSubTable:
8472 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8474 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8476 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8477 pTrace_data = (const GLvoid *)ptr_val;
8480 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8484 case VOGL_ENTRYPOINT_glColorSubTableEXT:
8486 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8488 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8490 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8491 pTrace_data = (const GLvoid *)ptr_val;
8494 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8498 case VOGL_ENTRYPOINT_glColorTable:
8500 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8502 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8504 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8505 pTrace_table = (const GLvoid *)ptr_val;
8508 VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8512 case VOGL_ENTRYPOINT_glColorTableEXT:
8514 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8516 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8518 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8519 pTrace_table = (const GLvoid *)ptr_val;
8522 VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8526 case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8528 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8530 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8532 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8533 pTrace_image = (const GLvoid *)ptr_val;
8536 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8540 case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8542 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8544 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8546 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8547 pTrace_image = (const GLvoid *)ptr_val;
8550 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8554 case VOGL_ENTRYPOINT_glDrawPixels:
8556 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8558 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8560 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8561 pTrace_pixels = (const GLvoid *)ptr_val;
8564 VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8568 case VOGL_ENTRYPOINT_glPolygonStipple:
8570 VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8572 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8574 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8575 pTrace_mask = (const GLubyte *)ptr_val;
8578 VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8582 case VOGL_ENTRYPOINT_glTexImage1D:
8584 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8586 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8588 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8589 pTrace_pixels = (const GLvoid *)ptr_val;
8592 VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8596 case VOGL_ENTRYPOINT_glTexImage2D:
8598 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8600 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8602 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8603 pTrace_pixels = (const GLvoid *)ptr_val;
8606 VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8610 case VOGL_ENTRYPOINT_glTexImage3D:
8612 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8614 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8616 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8617 pTrace_pixels = (const GLvoid *)ptr_val;
8620 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8624 case VOGL_ENTRYPOINT_glTexImage3DEXT:
8626 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8628 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8630 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8631 pTrace_pixels = (const GLvoid *)ptr_val;
8634 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8638 case VOGL_ENTRYPOINT_glTexSubImage1D:
8640 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8642 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8644 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8645 pTrace_pixels = (const GLvoid *)ptr_val;
8648 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8652 case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8654 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8656 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8658 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8659 pTrace_pixels = (const GLvoid *)ptr_val;
8662 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8666 case VOGL_ENTRYPOINT_glTexSubImage2D:
8668 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8670 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8672 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8673 pTrace_pixels = (const GLvoid *)ptr_val;
8676 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8680 case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8682 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8684 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8686 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8687 pTrace_pixels = (const GLvoid *)ptr_val;
8690 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8694 case VOGL_ENTRYPOINT_glTexSubImage3D:
8696 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8698 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8700 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8701 pTrace_pixels = (const GLvoid *)ptr_val;
8704 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8708 case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8710 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8712 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8714 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8715 pTrace_pixels = (const GLvoid *)ptr_val;
8718 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8722 case VOGL_ENTRYPOINT_glAreTexturesResident:
8723 case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8724 case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8725 case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8726 case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8727 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8728 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8729 case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8730 case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8731 case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8732 case VOGL_ENTRYPOINT_glGetActiveUniformName:
8733 case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8734 case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8735 case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8736 case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8737 case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8738 case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8739 case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8740 case VOGL_ENTRYPOINT_glGetBooleani_v:
8741 case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8742 case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8743 case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8744 case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8745 case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8746 case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8747 case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8748 case VOGL_ENTRYPOINT_glGetColorTable:
8749 case VOGL_ENTRYPOINT_glGetColorTableEXT:
8750 case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8751 case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8752 case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8753 case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8754 case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8755 case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8756 case VOGL_ENTRYPOINT_glGetColorTableSGI:
8757 case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8758 case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8759 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8760 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8761 case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8762 case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8763 case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8764 case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8765 case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8766 case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8767 case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8768 case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8769 case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8770 case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8771 case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8772 case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8773 case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8774 case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8775 case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8776 case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8777 case VOGL_ENTRYPOINT_glGetDoublei_v:
8778 case VOGL_ENTRYPOINT_glGetFenceivNV:
8779 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8780 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8781 case VOGL_ENTRYPOINT_glGetFixedvOES:
8782 case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8783 case VOGL_ENTRYPOINT_glGetFloati_v:
8784 case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8785 case VOGL_ENTRYPOINT_glGetFragDataIndex:
8786 case VOGL_ENTRYPOINT_glGetFragDataLocation:
8787 case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8788 case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8789 case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8790 case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8791 case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8792 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8793 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8794 case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8795 case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8796 case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8797 case VOGL_ENTRYPOINT_glGetHandleARB:
8798 case VOGL_ENTRYPOINT_glGetHistogram:
8799 case VOGL_ENTRYPOINT_glGetHistogramEXT:
8800 case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8801 case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8802 case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8803 case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8804 case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8805 case VOGL_ENTRYPOINT_glGetImageHandleNV:
8806 case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8807 case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8808 case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8809 case VOGL_ENTRYPOINT_glGetInteger64i_v:
8810 case VOGL_ENTRYPOINT_glGetInteger64v:
8811 case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8812 case VOGL_ENTRYPOINT_glGetIntegeri_v:
8813 case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8814 case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8815 case VOGL_ENTRYPOINT_glGetInternalformati64v:
8816 case VOGL_ENTRYPOINT_glGetInternalformativ:
8817 case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8818 case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8819 case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8820 case VOGL_ENTRYPOINT_glGetLightxOES:
8821 case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8822 case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8823 case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8824 case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8825 case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8826 case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8827 case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8828 case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8829 case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8830 case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8831 case VOGL_ENTRYPOINT_glGetMapdv:
8832 case VOGL_ENTRYPOINT_glGetMapfv:
8833 case VOGL_ENTRYPOINT_glGetMapiv:
8834 case VOGL_ENTRYPOINT_glGetMapxvOES:
8835 case VOGL_ENTRYPOINT_glGetMaterialfv:
8836 case VOGL_ENTRYPOINT_glGetMaterialiv:
8837 case VOGL_ENTRYPOINT_glGetMaterialxOES:
8838 case VOGL_ENTRYPOINT_glGetMinmax:
8839 case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8840 case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8841 case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8842 case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8843 case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8844 case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8845 case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8846 case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8847 case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8848 case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8849 case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8850 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8851 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8852 case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8853 case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8854 case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8855 case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8856 case VOGL_ENTRYPOINT_glGetMultisamplefv:
8857 case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
8858 case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
8859 case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
8860 case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
8861 case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
8862 case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
8863 case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
8864 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
8865 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
8866 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
8867 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
8868 case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
8869 case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
8870 case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
8871 case VOGL_ENTRYPOINT_glGetNamedStringARB:
8872 case VOGL_ENTRYPOINT_glGetNamedStringivARB:
8873 case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
8874 case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
8875 case VOGL_ENTRYPOINT_glGetObjectLabel:
8876 case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
8877 case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
8878 case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8879 case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
8880 case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
8881 case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
8882 case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
8883 case VOGL_ENTRYPOINT_glGetPathCommandsNV:
8884 case VOGL_ENTRYPOINT_glGetPathCoordsNV:
8885 case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
8886 case VOGL_ENTRYPOINT_glGetPathLengthNV:
8887 case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
8888 case VOGL_ENTRYPOINT_glGetPathMetricsNV:
8889 case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
8890 case VOGL_ENTRYPOINT_glGetPathParameterivNV:
8891 case VOGL_ENTRYPOINT_glGetPathSpacingNV:
8892 case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
8893 case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
8894 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
8895 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
8896 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
8897 case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
8898 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
8899 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
8900 case VOGL_ENTRYPOINT_glGetPixelMapfv:
8901 case VOGL_ENTRYPOINT_glGetPixelMapuiv:
8902 case VOGL_ENTRYPOINT_glGetPixelMapusv:
8903 case VOGL_ENTRYPOINT_glGetPixelMapxv:
8904 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
8905 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
8906 case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
8907 case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
8908 case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
8909 case VOGL_ENTRYPOINT_glGetPointervEXT:
8910 case VOGL_ENTRYPOINT_glGetPolygonStipple:
8911 case VOGL_ENTRYPOINT_glGetProgramBinary:
8912 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
8913 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
8914 case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
8915 case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
8916 case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
8917 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
8918 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
8919 case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
8920 case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
8921 case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
8922 case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
8923 case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
8924 case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
8925 case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
8926 case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
8927 case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
8928 case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
8929 case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
8930 case VOGL_ENTRYPOINT_glGetProgramResourceName:
8931 case VOGL_ENTRYPOINT_glGetProgramResourceiv:
8932 case VOGL_ENTRYPOINT_glGetProgramStageiv:
8933 case VOGL_ENTRYPOINT_glGetProgramStringARB:
8934 case VOGL_ENTRYPOINT_glGetProgramStringNV:
8935 case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
8936 case VOGL_ENTRYPOINT_glGetProgramivNV:
8937 case VOGL_ENTRYPOINT_glGetQueryIndexediv:
8938 case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
8939 case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
8940 case VOGL_ENTRYPOINT_glGetQueryiv:
8941 case VOGL_ENTRYPOINT_glGetQueryivARB:
8942 case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
8943 case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
8944 case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
8945 case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
8946 case VOGL_ENTRYPOINT_glGetSeparableFilter:
8947 case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
8948 case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
8949 case VOGL_ENTRYPOINT_glGetShaderSource:
8950 case VOGL_ENTRYPOINT_glGetShaderSourceARB:
8951 case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
8952 case VOGL_ENTRYPOINT_glGetSubroutineIndex:
8953 case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
8954 case VOGL_ENTRYPOINT_glGetSynciv:
8955 case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
8956 case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
8957 case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
8958 case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
8959 case VOGL_ENTRYPOINT_glGetTexGenxvOES:
8960 case VOGL_ENTRYPOINT_glGetTexImage:
8961 case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
8962 case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
8963 case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
8964 case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
8965 case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
8966 case VOGL_ENTRYPOINT_glGetTextureHandleNV:
8967 case VOGL_ENTRYPOINT_glGetTextureImageEXT:
8968 case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
8969 case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
8970 case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
8971 case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
8972 case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
8973 case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
8974 case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
8975 case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
8976 case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
8977 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
8978 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
8979 case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
8980 case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
8981 case VOGL_ENTRYPOINT_glGetUniformIndices:
8982 case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
8983 case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
8984 case VOGL_ENTRYPOINT_glGetUniformdv:
8985 case VOGL_ENTRYPOINT_glGetUniformfv:
8986 case VOGL_ENTRYPOINT_glGetUniformfvARB:
8987 case VOGL_ENTRYPOINT_glGetUniformi64vNV:
8988 case VOGL_ENTRYPOINT_glGetUniformiv:
8989 case VOGL_ENTRYPOINT_glGetUniformivARB:
8990 case VOGL_ENTRYPOINT_glGetUniformui64vNV:
8991 case VOGL_ENTRYPOINT_glGetUniformuiv:
8992 case VOGL_ENTRYPOINT_glGetUniformuivEXT:
8993 case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
8994 case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
8995 case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
8996 case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
8997 case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
8998 case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
8999 case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9000 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9001 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9002 case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9003 case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9004 case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9005 case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9006 case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9007 case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9008 case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9009 case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9010 case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9011 case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9012 case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9013 case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9014 case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9015 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9016 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9017 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9018 case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9019 case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9020 case VOGL_ENTRYPOINT_glGetVideoivNV:
9021 case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9022 case VOGL_ENTRYPOINT_glGetVideouivNV:
9023 case VOGL_ENTRYPOINT_glGetnColorTableARB:
9024 case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9025 case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9026 case VOGL_ENTRYPOINT_glGetnHistogramARB:
9027 case VOGL_ENTRYPOINT_glGetnMapdvARB:
9028 case VOGL_ENTRYPOINT_glGetnMapfvARB:
9029 case VOGL_ENTRYPOINT_glGetnMapivARB:
9030 case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9031 case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9032 case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9033 case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9034 case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9035 case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9036 case VOGL_ENTRYPOINT_glGetnTexImageARB:
9037 case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9038 case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9039 case VOGL_ENTRYPOINT_glGetnUniformivARB:
9040 case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9041 case VOGL_ENTRYPOINT_glIsBufferARB:
9042 case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9043 case VOGL_ENTRYPOINT_glIsQueryARB:
9044 case VOGL_ENTRYPOINT_glIsSync:
9045 case VOGL_ENTRYPOINT_glPrioritizeTextures:
9046 case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9048 if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9050 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9052 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9058 if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9059 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);
9061 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);
9062 return cStatusSoftFailure;
9066 m_last_processed_call_counter = trace_packet.get_call_counter();
9068 if (!m_pCur_context_state->m_inside_gl_begin)
9070 if (check_gl_error())
9071 return cStatusGLError;
9074 if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9076 if ((status = post_draw_call()) != cStatusOK)
9083 //----------------------------------------------------------------------------------------------------------------------
9084 // vogl_gl_replayer::snapshot_backbuffer
9085 //----------------------------------------------------------------------------------------------------------------------
9086 void vogl_gl_replayer::snapshot_backbuffer()
9090 if (!m_pCur_context_state)
9092 vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9096 uint recorded_width = m_pWindow->get_width();
9097 uint recorded_height = m_pWindow->get_height();
9099 uint width = 0, height = 0;
9100 m_pWindow->get_actual_dimensions(width, height);
9102 VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9103 VOGL_NOTE_UNUSED(recorded_width);
9104 VOGL_NOTE_UNUSED(recorded_height);
9106 m_screenshot_buffer.resize(width * height * 3);
9108 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);
9111 process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9114 if (m_flags & cGLReplayerDumpScreenshots)
9116 size_t png_size = 0;
9117 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9119 dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9120 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9122 process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9126 vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9132 if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9134 uint64_t backbuffer_crc64;
9136 if (m_flags & cGLReplayerSumHashing)
9138 backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9142 backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9145 vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9147 if (m_backbuffer_hash_filename.has_content())
9149 FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9151 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9154 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9161 //----------------------------------------------------------------------------------------------------------------------
9162 // vogl_gl_replayer::is_valid_handle
9163 //----------------------------------------------------------------------------------------------------------------------
9164 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9171 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9173 switch (handle_namespace)
9175 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9177 VOGL_ASSERT(replay_handle32 == replay_handle);
9178 return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9180 case VOGL_NAMESPACE_FRAMEBUFFERS:
9182 VOGL_ASSERT(replay_handle32 == replay_handle);
9183 return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9185 case VOGL_NAMESPACE_TEXTURES:
9187 VOGL_ASSERT(replay_handle32 == replay_handle);
9188 return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9190 case VOGL_NAMESPACE_RENDER_BUFFERS:
9192 VOGL_ASSERT(replay_handle32 == replay_handle);
9193 return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9195 case VOGL_NAMESPACE_QUERIES:
9197 VOGL_ASSERT(replay_handle32 == replay_handle);
9198 return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9200 case VOGL_NAMESPACE_SAMPLERS:
9202 VOGL_ASSERT(replay_handle32 == replay_handle);
9203 return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9205 case VOGL_NAMESPACE_PROGRAMS:
9207 VOGL_ASSERT(replay_handle32 == replay_handle);
9208 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9210 case VOGL_NAMESPACE_SHADERS:
9212 VOGL_ASSERT(replay_handle32 == replay_handle);
9213 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9215 case VOGL_NAMESPACE_BUFFERS:
9217 VOGL_ASSERT(replay_handle32 == replay_handle);
9218 return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9220 case VOGL_NAMESPACE_SYNCS:
9222 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9223 return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9225 case VOGL_NAMESPACE_PROGRAM_ARB:
9227 VOGL_ASSERT(replay_handle32 == replay_handle);
9228 return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9239 //----------------------------------------------------------------------------------------------------------------------
9240 // vogl_gl_replayer::remap_handle
9241 //----------------------------------------------------------------------------------------------------------------------
9242 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9249 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9251 switch (handle_namespace)
9253 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9255 VOGL_ASSERT(replay_handle32 == replay_handle);
9256 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9257 return replay_handle32;
9260 case VOGL_NAMESPACE_FRAMEBUFFERS:
9262 VOGL_ASSERT(replay_handle32 == replay_handle);
9263 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9264 return replay_handle32;
9267 case VOGL_NAMESPACE_TEXTURES:
9269 VOGL_ASSERT(replay_handle32 == replay_handle);
9271 uint32 trace_handle = replay_handle32;
9272 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9273 return trace_handle;
9277 case VOGL_NAMESPACE_RENDER_BUFFERS:
9279 VOGL_ASSERT(replay_handle32 == replay_handle);
9280 GLuint trace_handle = replay_handle32;
9281 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9282 return trace_handle;
9286 case VOGL_NAMESPACE_QUERIES:
9288 VOGL_ASSERT(replay_handle32 == replay_handle);
9289 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9290 return replay_handle32;
9293 case VOGL_NAMESPACE_SAMPLERS:
9295 VOGL_ASSERT(replay_handle32 == replay_handle);
9296 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9297 return replay_handle32;
9300 case VOGL_NAMESPACE_PROGRAMS:
9302 VOGL_ASSERT(replay_handle32 == replay_handle);
9303 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9304 GLuint trace_handle = replay_handle32;
9305 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9306 return trace_handle;
9309 case VOGL_NAMESPACE_SHADERS:
9311 VOGL_ASSERT(replay_handle32 == replay_handle);
9312 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9313 GLuint trace_handle = replay_handle32;
9314 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9315 return trace_handle;
9318 case VOGL_NAMESPACE_BUFFERS:
9320 VOGL_ASSERT(replay_handle32 == replay_handle);
9321 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9322 return replay_handle32;
9325 case VOGL_NAMESPACE_SYNCS:
9327 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9329 gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9330 if (it != m_replayer.get_shared_state()->m_syncs.end())
9332 VOGL_ASSERT(it->second == replay_sync);
9338 case VOGL_NAMESPACE_PROGRAM_ARB:
9340 VOGL_ASSERT(replay_handle32 == replay_handle);
9341 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9342 return replay_handle32;
9352 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));
9356 return replay_handle;
9359 //----------------------------------------------------------------------------------------------------------------------
9360 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9361 //----------------------------------------------------------------------------------------------------------------------
9362 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9366 if ((!replay_program) || (replay_location < 0))
9367 return replay_location;
9369 GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9371 glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9372 if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9374 const glsl_program_state &state = it->second;
9376 uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9377 if (loc_it != state.m_uniform_locations.end())
9378 return loc_it->first;
9381 vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9383 return replay_location;
9386 //----------------------------------------------------------------------------------------------------------------------
9387 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9388 //----------------------------------------------------------------------------------------------------------------------
9389 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9395 uint32 handle32 = static_cast<uint32>(replay_handle);
9397 switch (handle_namespace)
9399 case VOGL_NAMESPACE_TEXTURES:
9401 VOGL_ASSERT(handle32 == replay_handle);
9402 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9405 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9416 //----------------------------------------------------------------------------------------------------------------------
9417 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9418 //----------------------------------------------------------------------------------------------------------------------
9419 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9425 uint32 handle32 = static_cast<uint32>(trace_handle);
9427 switch (handle_namespace)
9429 case VOGL_NAMESPACE_TEXTURES:
9431 VOGL_ASSERT(handle32 == trace_handle);
9432 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9435 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9446 //----------------------------------------------------------------------------------------------------------------------
9447 // vogl_replayer::determine_used_program_handles
9448 //----------------------------------------------------------------------------------------------------------------------
9449 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9453 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9456 GLint cur_program_handle = 0;
9457 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9460 if (cur_program_handle)
9461 replay_program_handles.insert(cur_program_handle);
9464 // Scan for bound programs on all contexts in this sharegroup
9465 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9466 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9468 context_state *pContext = it->second;
9469 if (pContext->m_pShared_state == pContext_shareroot)
9471 if (pContext->m_cur_replay_program)
9472 replay_program_handles.insert(pContext->m_cur_replay_program);
9476 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9478 if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9481 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9483 // 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.
9484 if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9487 GLuint trace_handle = 0;
9488 bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9489 if (!refers_to_program)
9494 // 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
9495 // 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).
9496 if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9499 uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9503 VOGL_ASSERT(utils::is_32bit(replay_handle));
9505 replay_program_handles.insert(static_cast<uint32>(replay_handle));
9508 vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9513 //----------------------------------------------------------------------------------------------------------------------
9514 // vogl_replayer::fill_replay_handle_hash_set
9515 //----------------------------------------------------------------------------------------------------------------------
9516 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)
9520 replay_handle_hash.reset();
9521 replay_handle_hash.reserve(trace_to_replay_hash.size());
9522 for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9524 // Insert replay handles into destination hash table
9525 bool success = replay_handle_hash.insert(it->second).second;
9526 VOGL_ASSERT(success);
9527 VOGL_NOTE_UNUSED(success);
9531 //----------------------------------------------------------------------------------------------------------------------
9532 // vogl_replayer::snapshot_state
9533 //----------------------------------------------------------------------------------------------------------------------
9534 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9538 timed_scope ts(VOGL_METHOD_NAME);
9540 vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9542 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,
9543 m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9545 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))
9547 vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9549 vogl_delete(pSnapshot);
9555 vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9556 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9557 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()));
9559 vogl_client_side_array_desc_vec client_side_array_ptrs;
9560 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9561 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()));
9563 vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9564 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9565 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()));
9567 pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9569 vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9571 context_hash_map::iterator it;
9572 for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9574 context_state *pContext_state = it->second;
9576 if (pContext_state->m_deleted)
9578 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));
9582 vogl_capture_context_params temp_shadow_state;
9583 vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9585 if (pContext_state->m_has_been_made_current)
9587 status_t status = switch_contexts(it->first);
9588 if (status != cStatusOK)
9590 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9594 VOGL_ASSERT(m_pCur_context_state == pContext_state);
9596 if (m_pCur_context_state->m_inside_gl_begin)
9598 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));
9599 pSnapshot->set_is_restorable(false);
9603 // Init the shadow state needed by the snapshot code.
9604 if (!m_pCur_context_state->is_root_context())
9606 // Only fill in non-shared state.
9607 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9608 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9612 pShadow_state = &m_pCur_context_state->m_shadow_state;
9614 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9616 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9617 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9618 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9621 pShadow_state->m_buffer_targets.reset();
9622 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)
9624 GLuint trace_handle = buf_it->first;
9625 GLuint replay_handle = buf_it->second;
9627 gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9628 if (target_it == get_shared_state()->m_buffer_targets.end())
9630 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);
9633 GLenum target = target_it->second;
9635 pShadow_state->m_buffer_targets.insert(replay_handle, target);
9639 pShadow_state->m_syncs.reset();
9640 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9641 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)
9643 bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9644 VOGL_ASSERT(success);
9645 VOGL_NOTE_UNUSED(success);
9648 // Program handles filter
9649 pShadow_state->m_filter_program_handles = false;
9650 pShadow_state->m_program_handles_filter.reset();
9653 // 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).
9654 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9655 if ((pTrim_packets) && (optimize_snapshot))
9657 if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9659 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9660 pShadow_state->m_program_handles_filter.clear();
9664 pShadow_state->m_filter_program_handles = true;
9668 VOGL_NOTE_UNUSED(optimize_snapshot);
9669 VOGL_NOTE_UNUSED(pTrim_packets);
9672 // ARB program targets
9673 pShadow_state->m_arb_program_targets.reset();
9674 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)
9676 GLuint trace_handle = arb_prog_it->first;
9677 GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9678 if ((!trace_handle) || (!replay_handle))
9684 GLenum target = arb_prog_it->second;
9685 pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9688 // Deal with any currently mapped buffers.
9689 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9691 pShadow_state->m_mapped_buffers = mapped_bufs;
9693 if (mapped_bufs.size())
9695 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());
9697 for (uint i = 0; i < mapped_bufs.size(); i++)
9699 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9701 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9703 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9704 VOGL_CHECK_GL_ERROR;
9706 GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9707 VOGL_CHECK_GL_ERROR;
9711 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9712 VOGL_CHECK_GL_ERROR;
9716 } // if (!m_pCur_context_state->is_root_context())
9718 } // if (pContext_state->m_has_been_made_current)
9720 if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9722 vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9726 if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9728 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9730 // Now remap any mapped buffers
9731 for (uint i = 0; i < mapped_bufs.size(); i++)
9733 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9735 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9737 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9738 VOGL_CHECK_GL_ERROR;
9742 desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9743 VOGL_CHECK_GL_ERROR;
9747 desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9748 VOGL_CHECK_GL_ERROR;
9751 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9752 VOGL_CHECK_GL_ERROR;
9758 if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9760 vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9764 vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9766 vogl_delete(pSnapshot);
9773 //----------------------------------------------------------------------------------------------------------------------
9774 // vogl_replayer::reset_state
9775 //----------------------------------------------------------------------------------------------------------------------
9776 void vogl_gl_replayer::reset_state()
9780 // Purposely does NOT destroy the cached snapshots
9782 destroy_pending_snapshot();
9785 m_pending_make_current_packet.clear();
9786 m_pending_window_resize_width = 0;
9787 m_pending_window_resize_height = 0;
9788 m_pending_window_resize_attempt_counter = 0;
9791 m_last_parsed_call_counter = -1;
9792 m_last_processed_call_counter = -1;
9793 m_at_frame_boundary = true;
9795 m_cur_trace_context = 0;
9796 m_cur_replay_context = 0;
9797 m_pCur_context_state = NULL;
9800 //if (m_pWindow->is_opened())
9801 // m_pWindow->clear_window();
9804 //----------------------------------------------------------------------------------------------------------------------
9805 // trace_to_replay_handle_remapper::is_valid_handle
9806 //----------------------------------------------------------------------------------------------------------------------
9807 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9814 uint32 from_handle32 = static_cast<uint32>(from_handle);
9816 switch (handle_namespace)
9818 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9820 VOGL_ASSERT(from_handle32 == from_handle);
9821 return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9823 case VOGL_NAMESPACE_TEXTURES:
9825 VOGL_ASSERT(from_handle32 == from_handle);
9826 return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9828 case VOGL_NAMESPACE_SAMPLERS:
9830 VOGL_ASSERT(from_handle32 == from_handle);
9831 return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9833 case VOGL_NAMESPACE_BUFFERS:
9835 VOGL_ASSERT(from_handle32 == from_handle);
9836 return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9838 case VOGL_NAMESPACE_SHADERS:
9839 case VOGL_NAMESPACE_PROGRAMS:
9841 VOGL_ASSERT(from_handle32 == from_handle);
9842 return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9844 case VOGL_NAMESPACE_FRAMEBUFFERS:
9846 VOGL_ASSERT(from_handle32 == from_handle);
9847 return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9849 case VOGL_NAMESPACE_RENDER_BUFFERS:
9851 VOGL_ASSERT(from_handle32 == from_handle);
9852 return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9854 case VOGL_NAMESPACE_QUERIES:
9856 VOGL_ASSERT(from_handle32 == from_handle);
9857 return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9859 case VOGL_NAMESPACE_SYNCS:
9861 return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
9863 case VOGL_NAMESPACE_PROGRAM_ARB:
9865 return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
9876 //----------------------------------------------------------------------------------------------------------------------
9877 // trace_to_replay_handle_remapper::remap_handle
9878 //----------------------------------------------------------------------------------------------------------------------
9879 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9886 uint32 from_handle32 = static_cast<uint32>(from_handle);
9888 switch (handle_namespace)
9890 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9892 VOGL_ASSERT(from_handle32 == from_handle);
9893 return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
9895 case VOGL_NAMESPACE_TEXTURES:
9897 VOGL_ASSERT(from_handle32 == from_handle);
9899 uint32 replay_handle = from_handle32;
9900 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
9901 return replay_handle;
9904 case VOGL_NAMESPACE_SAMPLERS:
9906 VOGL_ASSERT(from_handle32 == from_handle);
9907 return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
9909 case VOGL_NAMESPACE_BUFFERS:
9911 VOGL_ASSERT(from_handle32 == from_handle);
9912 return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
9914 case VOGL_NAMESPACE_SHADERS:
9915 case VOGL_NAMESPACE_PROGRAMS:
9917 VOGL_ASSERT(from_handle32 == from_handle);
9919 GLuint replay_handle = from_handle32;
9920 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
9921 return replay_handle;
9924 case VOGL_NAMESPACE_FRAMEBUFFERS:
9926 VOGL_ASSERT(from_handle32 == from_handle);
9927 return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
9929 case VOGL_NAMESPACE_RENDER_BUFFERS:
9931 VOGL_ASSERT(from_handle32 == from_handle);
9933 GLuint replay_handle = from_handle32;
9934 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
9935 return replay_handle;
9939 case VOGL_NAMESPACE_QUERIES:
9941 VOGL_ASSERT(from_handle32 == from_handle);
9942 return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
9944 case VOGL_NAMESPACE_SYNCS:
9946 return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
9948 case VOGL_NAMESPACE_PROGRAM_ARB:
9950 return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
9960 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
9965 //----------------------------------------------------------------------------------------------------------------------
9966 // trace_to_replay_handle_remapper::remap_location
9967 //----------------------------------------------------------------------------------------------------------------------
9968 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
9972 VOGL_NOTE_UNUSED(trace_program);
9974 // restoring declares, but doesn't need to remap
9977 return from_location;
9980 //----------------------------------------------------------------------------------------------------------------------
9981 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
9982 //----------------------------------------------------------------------------------------------------------------------
9983 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
9990 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
9991 if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
9993 m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9996 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
9999 //----------------------------------------------------------------------------------------------------------------------
10000 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10001 //----------------------------------------------------------------------------------------------------------------------
10002 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)
10006 VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10011 if (id == vogl_texcoord_pointer_array_id)
10013 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10015 if (!m_replayer.m_client_side_texcoord_data[index].size())
10017 m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10020 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10024 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10026 if (!m_replayer.m_client_side_array_data[id].size())
10028 m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10031 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10035 //----------------------------------------------------------------------------------------------------------------------
10036 // trace_to_replay_handle_remapper::declare_handle
10037 //----------------------------------------------------------------------------------------------------------------------
10038 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)
10042 if ((!from_handle) || (!to_handle))
10044 VOGL_ASSERT_ALWAYS;
10048 uint32 from_handle32 = static_cast<uint32>(from_handle);
10049 uint32 to_handle32 = static_cast<uint32>(to_handle);
10051 switch (handle_namespace)
10053 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10055 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10056 m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10059 case VOGL_NAMESPACE_TEXTURES:
10061 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10062 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10063 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);
10066 case VOGL_NAMESPACE_SAMPLERS:
10068 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10069 m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10072 case VOGL_NAMESPACE_BUFFERS:
10074 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10075 m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10076 m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10079 case VOGL_NAMESPACE_SHADERS:
10081 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10082 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10083 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);
10086 case VOGL_NAMESPACE_PROGRAMS:
10088 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10089 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10090 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);
10093 case VOGL_NAMESPACE_FRAMEBUFFERS:
10095 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10096 m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10099 case VOGL_NAMESPACE_RENDER_BUFFERS:
10101 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10102 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10103 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);
10106 case VOGL_NAMESPACE_QUERIES:
10108 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10109 m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10110 m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10113 case VOGL_NAMESPACE_SYNCS:
10115 m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10118 case VOGL_NAMESPACE_PROGRAM_ARB:
10120 m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10121 m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10132 //----------------------------------------------------------------------------------------------------------------------
10133 // trace_to_replay_handle_remapper::delete_handle_and_object
10134 //----------------------------------------------------------------------------------------------------------------------
10135 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)
10139 if ((!from_handle) || (!to_handle))
10141 VOGL_ASSERT_ALWAYS;
10145 uint32 from_handle32 = static_cast<uint32>(from_handle);
10146 uint32 to_handle32 = static_cast<uint32>(to_handle);
10147 VOGL_NOTE_UNUSED(to_handle32);
10149 switch (handle_namespace)
10151 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10153 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10154 m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10155 vogl_destroy_gl_object(handle_namespace, to_handle);
10158 case VOGL_NAMESPACE_TEXTURES:
10160 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10161 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10162 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);
10164 vogl_destroy_gl_object(handle_namespace, to_handle);
10167 case VOGL_NAMESPACE_SAMPLERS:
10169 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10170 m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10171 vogl_destroy_gl_object(handle_namespace, to_handle);
10174 case VOGL_NAMESPACE_BUFFERS:
10176 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10177 m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10178 m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10179 vogl_destroy_gl_object(handle_namespace, to_handle);
10182 case VOGL_NAMESPACE_SHADERS:
10184 m_replayer.handle_delete_shader(from_handle32);
10187 case VOGL_NAMESPACE_PROGRAMS:
10189 m_replayer.handle_delete_program(from_handle32);
10192 case VOGL_NAMESPACE_FRAMEBUFFERS:
10194 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10195 m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10196 vogl_destroy_gl_object(handle_namespace, to_handle);
10199 case VOGL_NAMESPACE_RENDER_BUFFERS:
10201 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10203 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10204 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);
10206 vogl_destroy_gl_object(handle_namespace, to_handle);
10209 case VOGL_NAMESPACE_QUERIES:
10211 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10212 m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10213 vogl_destroy_gl_object(handle_namespace, to_handle);
10216 case VOGL_NAMESPACE_SYNCS:
10218 m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10219 vogl_destroy_gl_object(handle_namespace, to_handle);
10222 case VOGL_NAMESPACE_PROGRAM_ARB:
10224 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10225 m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10226 m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10227 vogl_destroy_gl_object(handle_namespace, to_handle);
10238 //----------------------------------------------------------------------------------------------------------------------
10239 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10240 //----------------------------------------------------------------------------------------------------------------------
10241 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)
10245 GLuint check_replay_handle = 0;
10246 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10247 VOGL_ASSERT(check_replay_handle == to_program_handle);
10248 VOGL_NOTE_UNUSED(check_replay_handle);
10250 VOGL_NOTE_UNUSED(to_program_handle);
10252 glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10254 glsl_program_state &prog_state = it->second;
10256 VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10258 prog_state.m_uniform_locations.insert(from_location, to_location);
10261 //----------------------------------------------------------------------------------------------------------------------
10262 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10263 //----------------------------------------------------------------------------------------------------------------------
10264 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10270 uint32 handle32 = static_cast<uint32>(trace_handle);
10272 switch (handle_namespace)
10274 case VOGL_NAMESPACE_TEXTURES:
10276 VOGL_ASSERT(handle32 == trace_handle);
10277 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10280 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10291 //----------------------------------------------------------------------------------------------------------------------
10292 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10293 //----------------------------------------------------------------------------------------------------------------------
10294 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10300 uint32 handle32 = static_cast<uint32>(replay_handle);
10302 switch (handle_namespace)
10304 case VOGL_NAMESPACE_TEXTURES:
10306 VOGL_ASSERT(handle32 == replay_handle);
10307 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10310 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10321 //----------------------------------------------------------------------------------------------------------------------
10322 // vogl_replayer::restore_objects
10323 //----------------------------------------------------------------------------------------------------------------------
10324 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10325 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,
10326 vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10330 VOGL_NOTE_UNUSED(snapshot);
10332 if (m_flags & cGLReplayerVerboseMode)
10333 vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10336 if (m_flags & cGLReplayerVerboseMode)
10339 const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10343 for (uint i = 0; i < object_ptrs.size(); i++)
10345 const vogl_gl_object_state *pState_obj = object_ptrs[i];
10347 if (pState_obj->get_type() != state_type)
10350 GLuint64 restore_handle = 0;
10351 if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10353 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);
10354 return cStatusHardFailure;
10358 if (pState_obj->get_marked_for_deletion())
10360 objects_to_delete.push_back(pState_obj);
10363 VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10365 switch (pState_obj->get_type())
10369 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10371 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10372 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10378 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10380 if (pProg->has_link_time_snapshot())
10382 vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10383 if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10385 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);
10389 get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10393 if (m_flags & cGLReplayerVerboseMode)
10395 if ((n & 255) == 255)
10396 vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10403 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10405 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10406 if (pBuf->get_is_mapped())
10408 vogl_mapped_buffer_desc map_desc;
10409 map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10410 map_desc.m_target = pBuf->get_target();
10411 map_desc.m_offset = pBuf->get_map_ofs();
10412 map_desc.m_length = pBuf->get_map_size();
10413 map_desc.m_access = pBuf->get_map_access();
10414 map_desc.m_range = pBuf->get_is_map_range();
10416 GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10418 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10419 VOGL_CHECK_GL_ERROR;
10421 if (map_desc.m_range)
10423 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);
10424 VOGL_CHECK_GL_ERROR;
10428 map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10429 VOGL_CHECK_GL_ERROR;
10432 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10433 VOGL_CHECK_GL_ERROR;
10435 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10436 mapped_bufs.push_back(map_desc);
10446 if (m_flags & cGLReplayerVerboseMode)
10449 vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10451 vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10457 //----------------------------------------------------------------------------------------------------------------------
10458 // vogl_xfont_cache
10459 //----------------------------------------------------------------------------------------------------------------------
10460 class vogl_xfont_cache
10462 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10465 vogl_xfont_cache(Display *dpy)
10471 ~vogl_xfont_cache()
10482 for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10483 XFreeFont(m_dpy, it->second);
10487 XFontStruct *get_or_create(const char *pName)
10491 XFontStruct **ppXFont = m_xfonts.find_value(pName);
10495 XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10497 m_xfonts.insert(pName, pXFont);
10505 typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10506 xfont_map m_xfonts;
10509 //----------------------------------------------------------------------------------------------------------------------
10510 // vogl_replayer::restore_display_lists
10511 //----------------------------------------------------------------------------------------------------------------------
10512 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)
10516 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10517 VOGL_NOTE_UNUSED(snapshot);
10519 VOGL_ASSERT(m_cur_trace_context);
10523 const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10525 if (!disp_lists.size())
10528 vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10530 vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10532 const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10534 for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10536 GLuint trace_handle = it->first;
10537 const vogl_display_list &disp_list = it->second;
10541 VOGL_ASSERT_ALWAYS;
10545 GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10546 if (check_gl_error() || !replay_handle)
10547 goto handle_failure;
10549 if (disp_list.is_valid())
10551 if (disp_list.is_xfont())
10553 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10556 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);
10560 GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10565 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10567 if (check_gl_error() || !replay_handle)
10569 GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10572 goto handle_failure;
10575 const vogl_trace_packet_array &packets = disp_list.get_packets();
10577 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10579 if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10581 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);
10585 const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10587 if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10589 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);
10593 vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10595 gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10597 if (m_flags & cGLReplayerDebugMode)
10598 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10600 int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10601 int64_t prev_processed_call_counter = m_last_processed_call_counter;
10602 m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10603 m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10604 bool prev_at_frame_boundary = m_at_frame_boundary;
10606 const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10608 m_pCur_gl_packet = &m_temp2_gl_packet;
10610 vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10612 m_pCur_gl_packet = pPrev_gl_packet;
10614 m_last_parsed_call_counter = prev_parsed_call_counter;
10615 m_last_processed_call_counter = prev_processed_call_counter;
10616 m_at_frame_boundary = prev_at_frame_boundary;
10618 if (status != cStatusOK)
10620 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);
10625 // TODO: Set context state because we're currently generating a display list!
10626 if (disp_list.is_generating())
10628 VOGL_ASSERT_ALWAYS;
10631 GL_ENTRYPOINT(glEndList)();
10636 get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10638 if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10640 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);
10646 vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10651 return cStatusHardFailure;
10654 //----------------------------------------------------------------------------------------------------------------------
10655 // vogl_replayer::restore_general_state
10656 //----------------------------------------------------------------------------------------------------------------------
10657 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)
10661 VOGL_NOTE_UNUSED(snapshot);
10663 vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10664 persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10666 if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10667 return cStatusHardFailure;
10669 if (!m_pCur_context_state->m_context_info.is_core_profile())
10671 if (context_snapshot.get_texenv_state().is_valid())
10673 if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10674 return cStatusHardFailure;
10677 if (context_snapshot.get_material_state().is_valid())
10679 if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10680 return cStatusHardFailure;
10683 if (context_snapshot.get_light_state().is_valid())
10685 if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10686 return cStatusHardFailure;
10689 if (context_snapshot.get_matrix_state().is_valid())
10691 if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10692 return cStatusHardFailure;
10695 if (context_snapshot.get_polygon_stipple_state().is_valid())
10697 if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10698 return cStatusHardFailure;
10701 if (context_snapshot.get_arb_program_environment_state().is_valid())
10703 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10705 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10706 return cStatusHardFailure;
10710 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);
10715 if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10717 if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10718 return cStatusHardFailure;
10724 //----------------------------------------------------------------------------------------------------------------------
10725 // vogl_replayer::validate_program_and_shader_handle_tables
10726 //----------------------------------------------------------------------------------------------------------------------
10727 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10731 if (!m_pCur_context_state)
10734 if (!get_shared_state()->m_shadow_state.m_objs.check())
10735 vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10737 uint_vec replay_handles;
10738 get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10740 for (uint i = 0; i < replay_handles.size(); i++)
10742 GLuint replay_handle = replay_handles[i];
10743 GLuint trace_handle = replay_handle;
10744 bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10745 VOGL_ASSERT(map_succeeded);
10746 VOGL_NOTE_UNUSED(map_succeeded);
10748 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10749 VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10751 if (target == VOGL_PROGRAM_OBJECT)
10753 if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10755 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);
10758 if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10760 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);
10763 else if (target == VOGL_SHADER_OBJECT)
10765 if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10767 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);
10772 VOGL_ASSERT_ALWAYS;
10779 //----------------------------------------------------------------------------------------------------------------------
10780 // vogl_replayer::validate_textures
10781 //----------------------------------------------------------------------------------------------------------------------
10782 bool vogl_gl_replayer::validate_textures()
10786 if (!m_pCur_context_state)
10789 if (!get_shared_state()->m_shadow_state.m_textures.check())
10790 vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10792 for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10794 bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10796 bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10800 if (found_in_shadow)
10802 GLuint trace_handle = 0;
10803 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10804 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);
10809 if (!found_in_shadow)
10811 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);
10819 //----------------------------------------------------------------------------------------------------------------------
10820 // vogl_replayer::update_context_shadows
10821 //----------------------------------------------------------------------------------------------------------------------
10822 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)
10826 VOGL_NOTE_UNUSED(snapshot);
10827 VOGL_NOTE_UNUSED(context_snapshot);
10828 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10832 // Make sure shadow is good
10833 GLint actual_current_replay_program = 0;
10834 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10837 m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10838 if (!actual_current_replay_program)
10839 m_pCur_context_state->m_cur_trace_program = 0;
10842 GLuint trace_handle = actual_current_replay_program;
10843 if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10845 process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10847 m_pCur_context_state->m_cur_replay_program = 0;
10848 m_pCur_context_state->m_cur_trace_program = 0;
10852 m_pCur_context_state->m_cur_trace_program = trace_handle;
10856 check_program_binding_shadow();
10861 //----------------------------------------------------------------------------------------------------------------------
10862 // vogl_replayer::handle_marked_for_deleted_objects
10863 //----------------------------------------------------------------------------------------------------------------------
10864 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)
10868 if (m_flags & cGLReplayerVerboseMode)
10870 vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
10873 for (uint i = 0; i < objects_to_delete.size(); i++)
10875 const vogl_gl_object_state *pState_obj = objects_to_delete[i];
10877 GLuint64 trace_handle = pState_obj->get_snapshot_handle();
10878 GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
10880 if (m_flags & cGLReplayerVerboseMode)
10882 // This should be a rare/exception case so let's try to be a little paranoid.
10883 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,
10884 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10887 GLboolean object_is_still_a_name = true;
10889 switch (pState_obj->get_type())
10893 handle_delete_program(static_cast<GLuint>(trace_handle));
10895 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
10901 handle_delete_shader(static_cast<GLuint>(trace_handle));
10903 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
10909 VOGL_ASSERT_ALWAYS;
10914 // "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."
10915 // Same for shaders.
10916 if (!object_is_still_a_name)
10918 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,
10919 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10924 //----------------------------------------------------------------------------------------------------------------------
10925 // vogl_replayer::begin_applying_snapshot
10926 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
10927 //----------------------------------------------------------------------------------------------------------------------
10928 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
10932 if (!pSnapshot->is_valid())
10934 if (delete_snapshot_after_applying)
10935 vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
10937 return cStatusHardFailure;
10942 m_pPending_snapshot = pSnapshot;
10943 m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
10945 m_frame_index = pSnapshot->get_frame_index();
10946 m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
10947 m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
10948 m_at_frame_boundary = false;
10950 if (!(m_flags & cGLReplayerLockWindowDimensions))
10952 return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
10955 return process_applying_pending_snapshot();
10958 //----------------------------------------------------------------------------------------------------------------------
10959 // vogl_replayer::restore_context
10960 //----------------------------------------------------------------------------------------------------------------------
10961 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)
10965 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10966 VOGL_NOTE_UNUSED(snapshot);
10968 // TODO: This always creates with attribs, also need to support plain glXCreateContext()
10970 Display *dpy = m_pWindow->get_display();
10971 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
10973 vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
10975 GLXContext replay_share_context = remap_context(trace_share_context);
10976 if ((trace_share_context) && (!replay_share_context))
10978 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));
10979 return cStatusHardFailure;
10982 GLboolean direct = context_snapshot.get_context_desc().get_direct();
10984 vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
10986 status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
10987 context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
10988 context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
10989 if (status != cStatusOK)
10991 vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
10995 // Has this context ever been made current?
10996 if (context_snapshot.get_context_info().is_valid())
10998 context_state *pContext_state = get_trace_context_state(trace_context);
10999 if (!pContext_state)
11001 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11002 return cStatusHardFailure;
11005 GLXContext replay_context = pContext_state->m_replay_context;
11006 if (!replay_context)
11008 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11009 return cStatusHardFailure;
11012 GLXDrawable drawable = m_pWindow->get_xwindow();
11014 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11017 vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11018 return cStatusHardFailure;
11021 m_cur_trace_context = trace_context;
11022 m_cur_replay_context = replay_context;
11023 m_pCur_context_state = pContext_state;
11025 if (!handle_context_made_current())
11026 return cStatusHardFailure;
11032 //----------------------------------------------------------------------------------------------------------------------
11033 // vogl_replayer::process_applying_pending_snapshot
11034 //----------------------------------------------------------------------------------------------------------------------
11035 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11039 if (!m_pPending_snapshot)
11042 timed_scope ts(VOGL_METHOD_NAME);
11044 const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11046 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11048 m_frame_index = snapshot.get_frame_index();
11049 m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11050 m_last_processed_call_counter = snapshot.get_gl_call_counter();
11051 m_at_frame_boundary = snapshot.get_at_frame_boundary();
11053 // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11054 for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11055 m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11057 for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11058 m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11060 for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11061 m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11063 const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11065 vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11066 vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11068 status_t status = cStatusOK;
11069 uint total_contexts_restored = 0;
11070 bool restored_default_framebuffer = false;
11074 uint num_contexts_restored_in_this_pass = 0;
11076 for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11078 if (!restore_context_ptrs[context_index])
11081 const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11083 if (context_state.get_context_desc().get_trace_share_context())
11085 // Don't restore this context if its sharelist context hasn't been restored yet
11086 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11090 status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11091 if (status != cStatusOK)
11094 // Has this context ever been made current?
11095 if (context_state.get_context_info().is_valid())
11097 // 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!)
11098 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11099 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11101 if (m_flags & cGLReplayerLowLevelDebugMode)
11103 if (!validate_textures())
11104 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11107 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11109 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11111 status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11112 if (status != cStatusOK)
11115 if (m_flags & cGLReplayerLowLevelDebugMode)
11117 if (!validate_program_and_shader_handle_tables())
11118 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11120 if (!validate_textures())
11121 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11125 if (m_flags & cGLReplayerLowLevelDebugMode)
11127 if (!validate_textures())
11128 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11131 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11132 if (status != cStatusOK)
11135 // Restore default framebuffer
11136 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11138 restored_default_framebuffer = true;
11140 if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11142 vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11146 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11147 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11148 if (status != cStatusOK)
11151 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11152 if (status != cStatusOK)
11155 if (m_flags & cGLReplayerLowLevelDebugMode)
11157 if (!validate_program_and_shader_handle_tables())
11158 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11160 if (!validate_textures())
11161 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11165 num_contexts_restored_in_this_pass++;
11167 total_contexts_restored++;
11169 restore_context_ptrs[context_index] = NULL;
11172 if (!num_contexts_restored_in_this_pass)
11176 if (total_contexts_restored != snapshot.get_contexts().size())
11178 vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11182 for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11184 const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11186 if (!context_state.get_context_info().is_valid())
11189 status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11190 if (status != cStatusOK)
11192 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()));
11196 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11198 handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11201 destroy_pending_snapshot();
11212 //----------------------------------------------------------------------------------------------------------------------
11213 // vogl_gl_replayer::write_trim_file_internal
11214 //----------------------------------------------------------------------------------------------------------------------
11215 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)
11217 // Open the output trace
11218 // 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.
11219 const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11221 vogl_trace_packet trace_packet(&trace_gl_ctypes);
11223 // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11224 bool found_state_snapshot = false;
11225 dynamic_string binary_snapshot_id, text_snapshot_id;
11227 bool is_at_start_of_trace = false;
11228 VOGL_NOTE_UNUSED(is_at_start_of_trace);
11230 int demarcation_packet_index = -1;
11231 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11233 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11234 if (packet_type != cTSPTGLEntrypoint)
11237 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11239 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11240 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11243 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11245 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11249 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11250 if (cmd == cITCRDemarcation)
11252 is_at_start_of_trace = true;
11253 demarcation_packet_index = packet_index;
11255 else if (cmd == cITCRKeyValueMap)
11257 key_value_map &kvm = trace_packet.get_key_value_map();
11259 dynamic_string cmd_type(kvm.get_string("command_type"));
11261 if (cmd_type == "state_snapshot")
11263 found_state_snapshot = true;
11265 text_snapshot_id = kvm.get_string("id");
11266 binary_snapshot_id = kvm.get_string("binary_id");
11271 vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11272 if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11274 console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11278 if (found_state_snapshot)
11280 // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11281 if (trace_reader.get_archive_blob_manager().is_initialized())
11283 dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11284 for (uint i = 0; i < blob_files.size(); i++)
11286 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11289 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11291 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11293 vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11301 // Copy over the source trace's backtrace map, machine info, etc. files.
11302 if (trace_reader.get_archive_blob_manager().is_initialized())
11304 // compiler_info.json
11305 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);
11306 // machine_info.json
11307 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);
11308 // backtrace_map_syms.json
11309 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);
11310 // backtrace_map_addrs.json
11311 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);
11314 vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11316 if (!pTrim_snapshot.get())
11318 console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11322 pTrim_snapshot->set_frame_index(0);
11325 if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11327 console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11328 trace_writer.close();
11329 file_utils::delete_file(trim_filename.get_ptr());
11333 vogl::vector<char> snapshot_data;
11334 doc.serialize(snapshot_data, true, 0, false);
11336 uint8_vec binary_snapshot_data;
11337 doc.binary_serialize(binary_snapshot_data);
11339 pTrim_snapshot.reset();
11341 // Write the state_snapshot file to the trace archive
11342 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));
11343 if (snapshot_id.is_empty())
11345 console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11346 trace_writer.close();
11347 file_utils::delete_file(trim_filename.get_ptr());
11352 *pSnapshot_id = snapshot_id;
11354 snapshot_data.clear();
11356 // Write the binary_state_snapshot file to the trace archive
11357 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));
11358 if (binary_snapshot_id.is_empty())
11360 console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11361 trace_writer.close();
11362 file_utils::delete_file(trim_filename.get_ptr());
11366 binary_snapshot_data.clear();
11368 key_value_map snapshot_key_value_map;
11369 snapshot_key_value_map.insert("command_type", "state_snapshot");
11370 snapshot_key_value_map.insert("id", snapshot_id);
11371 snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11373 dynamic_stream snapshot_stream(0);
11374 if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11376 console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11377 trace_writer.close();
11378 file_utils::delete_file(trim_filename.get_ptr());
11382 if (demarcation_packet_index >= 0)
11384 trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11385 demarcation_packet_index++;
11389 dynamic_stream demarcation_stream(0);
11390 vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11392 // Screw the ctypes packet, it's only used for debugging right now anyway.
11393 trim_packets.insert(0, snapshot_stream.get_buf());
11394 trim_packets.insert(1, demarcation_stream.get_buf());
11398 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11400 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11402 const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11404 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11405 if (packet_type == cTSPTEOF)
11407 else if (packet_type != cTSPTGLEntrypoint)
11409 VOGL_ASSERT_ALWAYS;
11412 if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11414 console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11415 trace_writer.close();
11416 file_utils::delete_file(trim_filename.get_ptr());
11421 bool success = trace_writer.close();
11423 console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11425 console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11430 //----------------------------------------------------------------------------------------------------------------------
11431 // vogl_gl_replayer::write_trim_file
11432 //----------------------------------------------------------------------------------------------------------------------
11433 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)
11439 console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11443 bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11445 if ((!from_start_of_frame) || (!trim_len))
11446 flags &= ~cWriteTrimFileOptimizeSnapshot;
11448 const uint trim_frame = static_cast<uint>(get_frame_index());
11449 const int64_t trim_call_counter = get_last_parsed_call_counter();
11451 // Read the desired packets from the source trace file
11452 vogl_trace_packet_array trim_packets;
11454 if ((trim_len) || (!trim_frame))
11456 console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11458 uint frames_to_read = trim_len;
11459 if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11460 frames_to_read = 1;
11462 uint actual_trim_len = 0;
11463 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);
11464 if (read_packets_status == vogl_trace_file_reader::cFailed)
11466 console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11470 if (actual_trim_len != frames_to_read)
11472 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);
11475 if (from_start_of_frame)
11477 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);
11479 if ((!trim_frame) && (!trim_len))
11481 // 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.
11482 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11484 vogl_trace_packet_array new_trim_packets;
11486 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11488 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11490 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11491 if (packet_type != cTSPTGLEntrypoint)
11494 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11496 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11497 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11500 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11502 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11506 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11508 new_trim_packets.push_back(packet_buf);
11510 if (cmd == cITCRDemarcation)
11514 trim_packets.swap(new_trim_packets);
11517 else if (trim_call_counter >= 0)
11519 uint orig_num_packets = trim_packets.size();
11520 uint total_erased_packets = 0;
11522 // Remove any calls before the current one.
11523 for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11525 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11528 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11530 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11532 trim_packets.erase(static_cast<uint>(packet_index));
11535 total_erased_packets++;
11539 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());
11543 if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11545 console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11547 file_utils::delete_file(trim_filename.get_ptr());