1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_gl_replayer.cpp
27 #include "vogl_gl_replayer.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_sync_object.h"
30 #include "vogl_trace_file_writer.h"
31 #include "vogl_texture_format.h"
32 #include "gl_glx_replay_helper_macros.inc"
33 #include "vogl_backtrace.h"
35 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
36 #include "vogl_miniz.h"
38 #include "vogl_timer.h"
39 #include "vogl_file_utils.h"
41 #include "vogl_vector.h"
43 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC 129
44 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC 0x12345678
45 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC -999999.0f
47 //----------------------------------------------------------------------------------------------------------------------
48 // glInterleavedArrays helper table
49 //----------------------------------------------------------------------------------------------------------------------
50 struct interleaved_array_desc_entry_t
66 #define _2f (sizeof(GLfloat) * 2)
67 #define _3f (sizeof(GLfloat) * 3)
68 #define _4f (sizeof(GLfloat) * 4)
69 #define _5f (sizeof(GLfloat) * 5)
70 #define _6f (sizeof(GLfloat) * 6)
71 #define _7f (sizeof(GLfloat) * 7)
72 #define _8f (sizeof(GLfloat) * 8)
73 #define _9f (sizeof(GLfloat) * 9)
74 #define _10f (sizeof(GLfloat) * 10)
75 #define _11f (sizeof(GLfloat) * 11)
76 #define _12f (sizeof(GLfloat) * 12)
77 #define _15f (sizeof(GLfloat) * 15)
78 #define _c (sizeof(GL_UNSIGNED_BYTE) * 4)
80 static const interleaved_array_desc_entry_t vogl_g_interleaved_array_descs[] =
82 // format et ec en st sc sv tc pc pn pv s
83 { GL_V2F, false, false, false, 0, 0, 2, 0, 0, 0, 0, _2f },
84 { GL_V3F, false, false, false, 0, 0, 3, 0, 0, 0, 0, _3f },
85 { GL_C4UB_V2F, false, true, false, 0, 4, 2, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _2f },
86 { GL_C4UB_V3F, false, true, false, 0, 4, 3, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _3f },
87 { GL_C3F_V3F, false, true, false, 0, 3, 3, GL_FLOAT, 0, 0, _3f, _6f },
88 { GL_N3F_V3F, false, false, true, 0, 0, 3, 0, 0, 0, _3f, _6f },
89 { GL_C4F_N3F_V3F, false, true, true, 0, 4, 3, GL_FLOAT, 0, _4f, _7f, _10f },
90 { GL_T2F_V3F, true, false, false, 2, 0, 3, 0, 0, 0, _2f, _5f },
91 { GL_T4F_V4F, true, false, false, 4, 0, 4, 0, 0, 0, _4f, _8f },
92 { GL_T2F_C4UB_V3F, true, true, false, 2, 4, 3, GL_UNSIGNED_BYTE, _2f, 0, _c + _2f, _c + _5f },
93 { GL_T2F_C3F_V3F, true, true, false, 2, 3, 3, GL_FLOAT, 0, _2f, _5f, _8f },
94 { GL_T2F_N3F_V3F, true, false, true, 2, 0, 3, 0, 0, _2f, _5f, _8f },
95 { GL_T2F_C4F_N3F_V3F, true, true, true, 2, 4, 3, GL_FLOAT, _2f, _6f, _9f, _12f },
96 { GL_T4F_C4F_N3F_V4F, true, true, true, 4, 4, 4, GL_FLOAT, _4f, _8f, _11f, _15f }
113 #define VOGL_INTERLEAVED_ARRAY_SIZE (sizeof(vogl_g_interleaved_array_descs) / sizeof(vogl_g_interleaved_array_descs[0]))
115 //----------------------------------------------------------------------------------------------------------------------
116 // vogl_replayer::vogl_replayer
117 //----------------------------------------------------------------------------------------------------------------------
118 vogl_gl_replayer::vogl_gl_replayer()
120 m_swap_sleep_time(0),
121 m_dump_framebuffer_on_draw_prefix("screenshot"),
122 m_screenshot_prefix("screenshot"),
123 m_dump_framebuffer_on_draw_frame_index(-1),
124 m_dump_framebuffer_on_draw_first_gl_call_index(-1),
125 m_dump_framebuffer_on_draw_last_gl_call_index(-1),
126 m_ctypes_packet(&m_trace_gl_ctypes),
127 m_trace_pointer_size_in_bytes(0),
128 m_trace_pointer_size_in_uints(0),
129 m_temp_gl_packet(&m_trace_gl_ctypes),
130 m_temp2_gl_packet(&m_trace_gl_ctypes),
131 m_pCur_gl_packet(NULL),
133 m_pending_make_current_packet(&m_trace_gl_ctypes),
134 m_pending_window_resize_width(0),
135 m_pending_window_resize_height(0),
136 m_pending_window_resize_attempt_counter(false),
139 m_last_parsed_call_counter(-1),
140 m_last_processed_call_counter(-1),
141 m_cur_trace_context(0),
142 m_cur_replay_context(NULL),
143 m_pCur_context_state(NULL),
144 m_frame_draw_counter(0),
145 m_frame_draw_counter_kill_threshold(cUINT64_MAX),
147 m_pBlob_manager(NULL),
148 m_pPending_snapshot(NULL),
149 m_delete_pending_snapshot_after_applying(false),
150 m_replay_to_trace_remapper(*this)
154 m_trace_gl_ctypes.init();
157 //----------------------------------------------------------------------------------------------------------------------
158 // vogl_replayer::~vogl_replayer
159 //----------------------------------------------------------------------------------------------------------------------
160 vogl_gl_replayer::~vogl_gl_replayer()
167 //----------------------------------------------------------------------------------------------------------------------
168 // vogl_replayer::init
169 //----------------------------------------------------------------------------------------------------------------------
170 bool vogl_gl_replayer::init(uint flags, vogl_replay_window *pWindow, const vogl_trace_stream_start_of_file_packet &sof_packet, const vogl_blob_manager &blob_manager)
177 if ((!pWindow) || (!pWindow->is_opened()))
183 if ((sof_packet.m_pointer_sizes != sizeof(uint32)) && (sof_packet.m_pointer_sizes != sizeof(uint64_t)))
185 vogl_error_printf("%s: Invalid trace pointer size (%u)\n", VOGL_METHOD_NAME, m_sof_packet.m_pointer_sizes);
189 m_pBlob_manager = &blob_manager;
193 m_sof_packet = sof_packet;
194 m_trace_pointer_size_in_bytes = m_sof_packet.m_pointer_sizes;
195 m_trace_pointer_size_in_uints = m_sof_packet.m_pointer_sizes / sizeof(uint);
197 m_trace_gl_ctypes.init();
198 m_trace_gl_ctypes.change_pointer_sizes(m_trace_pointer_size_in_bytes);
200 if (!m_pWindow->is_opened())
202 const uint initial_window_width = 1024;
203 const uint initial_window_height = 768;
204 if (!m_pWindow->open(initial_window_width, initial_window_height))
206 vogl_error_printf("%s: Failed opening window!\n", VOGL_METHOD_NAME);
211 m_pCur_gl_packet = NULL;
215 m_last_parsed_call_counter = 0;
216 m_last_processed_call_counter = 0;
218 m_pending_make_current_packet.clear();
219 m_pending_window_resize_width = 0;
220 m_pending_window_resize_height = 0;
221 m_pending_window_resize_attempt_counter = 0;
223 m_at_frame_boundary = true;
225 m_cur_trace_context = 0;
226 m_cur_replay_context = 0;
227 m_pCur_context_state = NULL;
231 m_frame_draw_counter = 0;
232 m_frame_draw_counter_kill_threshold = cUINT64_MAX;
239 //----------------------------------------------------------------------------------------------------------------------
240 // vogl_replayer::deinit
241 //----------------------------------------------------------------------------------------------------------------------
242 void vogl_gl_replayer::deinit()
246 destroy_pending_snapshot();
249 // TODO: Make a 1st class snapshot cache class
250 for (uint i = 0; i < m_snapshots.size(); i++)
251 vogl_delete(m_snapshots[i].m_pSnapshot);
254 m_ctypes_packet.reset();
256 m_pCur_gl_packet = NULL;
260 m_last_parsed_call_counter = 0;
261 m_last_processed_call_counter = 0;
263 m_pending_make_current_packet.clear();
264 m_pending_window_resize_width = 0;
265 m_pending_window_resize_height = 0;
266 m_pending_window_resize_attempt_counter = 0;
268 m_at_frame_boundary = true;
270 m_cur_trace_context = 0;
271 m_cur_replay_context = 0;
272 m_pCur_context_state = NULL;
274 m_frame_draw_counter = 0;
275 m_frame_draw_counter_kill_threshold = cUINT32_MAX;
277 m_pBlob_manager = NULL;
280 m_swap_sleep_time = 0;
281 m_dump_framebuffer_on_draw_prefix = "screenshot";
282 m_screenshot_prefix = "screenshot";
283 m_backbuffer_hash_filename.clear();
284 m_dump_framebuffer_on_draw_frame_index = -1;
285 m_dump_framebuffer_on_draw_first_gl_call_index = -1;
286 m_dump_framebuffer_on_draw_last_gl_call_index = -1;
288 m_dump_frontbuffer_filename.clear();
293 //----------------------------------------------------------------------------------------------------------------------
294 // vogl_gl_replayer::dump_trace_gl_packet_debug_info
295 //----------------------------------------------------------------------------------------------------------------------
296 void vogl_gl_replayer::dump_trace_gl_packet_debug_info(const vogl_trace_gl_entrypoint_packet &gl_packet)
300 vogl_debug_printf("Trace packet: Total size %u, Param size: %u, Client mem size %u, Name value size %u, call %" PRIu64 ", ID: %s (%u), Thread ID: 0x%" PRIX64 ", Trace Context: 0x%" PRIX64 "\n",
302 gl_packet.m_param_size,
303 gl_packet.m_client_memory_size,
304 gl_packet.m_name_value_map_size,
305 gl_packet.m_call_counter,
306 g_vogl_entrypoint_descs[gl_packet.m_entrypoint_id].m_pName,
307 gl_packet.m_entrypoint_id,
308 gl_packet.m_thread_id,
309 gl_packet.m_context_handle);
312 //----------------------------------------------------------------------------------------------------------------------
313 // vogl_gl_replayer::dump_packet_as_func_call
314 //----------------------------------------------------------------------------------------------------------------------
315 void vogl_gl_replayer::dump_packet_as_func_call(const vogl_trace_packet& trace_packet)
321 if (!trace_packet.pretty_print(str, false))
322 vogl_error_printf("%s: packet pretty print failed!\n", VOGL_METHOD_NAME);
324 vogl_debug_printf("%s\n", str.get_ptr());
327 //----------------------------------------------------------------------------------------------------------------------
328 // vogl_replayer::process_next_packet
329 //----------------------------------------------------------------------------------------------------------------------
330 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(const vogl_trace_packet &gl_packet)
332 // TODO: Fix const correctness
333 return process_gl_entrypoint_packet((vogl_trace_packet &)gl_packet);
336 //----------------------------------------------------------------------------------------------------------------------
337 // vogl_replayer::process_next_packet
338 //----------------------------------------------------------------------------------------------------------------------
339 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(vogl_trace_file_reader &trace_reader)
343 vogl_trace_file_reader::trace_file_reader_status_t read_status = trace_reader.read_next_packet();
344 if (read_status == vogl_trace_file_reader::cEOF)
346 vogl_message_printf("At trace file EOF\n");
349 else if (read_status != vogl_trace_file_reader::cOK)
351 vogl_error_printf("Failed reading from trace file\n");
352 return cStatusHardFailure;
355 status_t status = cStatusOK;
357 switch (trace_reader.get_packet_type())
364 case cTSPTGLEntrypoint:
366 if (!m_temp_gl_packet.deserialize(trace_reader.get_packet_buf().get_ptr(), trace_reader.get_packet_buf().size(), false))
368 vogl_error_printf("Failed deserializing GL entrypoint packet\n");
369 status = cStatusHardFailure;
373 status = process_next_packet(m_temp_gl_packet);
379 vogl_message_printf("Encountered EOF packet in trace file\n");
380 status = cStatusAtEOF;
385 vogl_error_printf("Encountered unknown packet type in trace file\n");
386 status = cStatusSoftFailure;
393 vogl_error_printf("%s: %s failure processing GL entrypoint packet\n", VOGL_METHOD_NAME, (status == cStatusHardFailure) ? "Hard" : "Soft");
399 //----------------------------------------------------------------------------------------------------------------------
400 // vogl_replayer::process_pending_window_resize
401 //----------------------------------------------------------------------------------------------------------------------
402 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_window_resize(bool *pApplied_snapshot)
406 if (pApplied_snapshot)
407 *pApplied_snapshot = false;
409 status_t status = cStatusOK;
411 if (get_has_pending_window_resize())
413 status = process_frame_check_for_pending_window_resize();
414 if (status != cStatusOK)
418 if (m_pPending_snapshot)
420 if (pApplied_snapshot)
421 *pApplied_snapshot = true;
423 status_t status = process_applying_pending_snapshot();
424 if (status != cStatusOK)
431 //----------------------------------------------------------------------------------------------------------------------
432 // vogl_replayer::process_frame
433 //----------------------------------------------------------------------------------------------------------------------
434 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame(vogl_trace_file_reader &trace_reader)
438 status_t status = cStatusOK;
442 status = process_next_packet(trace_reader);
443 if ((status == cStatusNextFrame) || (status == cStatusResizeWindow) || (status == cStatusAtEOF) || (status == cStatusHardFailure))
450 //----------------------------------------------------------------------------------------------------------------------
451 // vogl_replayer::process_event
452 //----------------------------------------------------------------------------------------------------------------------
453 bool vogl_gl_replayer::update_window_dimensions()
457 m_pWindow->update_dimensions();
462 //----------------------------------------------------------------------------------------------------------------------
463 // vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap
464 //----------------------------------------------------------------------------------------------------------------------
465 bool vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap(const dynamic_string &filename)
467 m_dump_frontbuffer_filename = filename;
472 //----------------------------------------------------------------------------------------------------------------------
473 // vogl_gl_replayer::dump_frontbuffer_to_file
474 //----------------------------------------------------------------------------------------------------------------------
475 bool vogl_gl_replayer::dump_frontbuffer_to_file(const dynamic_string &filename)
477 if ((!m_is_valid) || (!m_pWindow))
483 uint width = 0, height = 0;
484 m_pWindow->get_actual_dimensions(width, height);
486 m_screenshot_buffer.resize(width * height * 3);
488 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_FRONT);
491 vogl_error_printf("%s: Failed calling glReadPixels() to take frontbuffer screenshot!\n", VOGL_METHOD_NAME);
496 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
498 success = file_utils::write_buf_to_file(filename.get_ptr(), pPNG_data, png_size);
501 vogl_error_printf("%s: Failed writing PNG screenshot to file \"%s\"\n", filename.get_ptr(), VOGL_METHOD_NAME);
505 vogl_message_printf("Wrote PNG screenshot to file \"%s\"\n", filename.get_ptr());
513 //----------------------------------------------------------------------------------------------------------------------
514 // vogl_replayer::trigger_pending_window_resize
515 //----------------------------------------------------------------------------------------------------------------------
516 vogl_gl_replayer::status_t vogl_gl_replayer::trigger_pending_window_resize(uint win_width, uint win_height)
520 m_pending_window_resize_width = win_width;
521 m_pending_window_resize_height = win_height;
522 m_pending_window_resize_attempt_counter = 0;
523 m_time_since_pending_window_resize.start();
525 m_pWindow->resize(win_width, win_height);
527 if (m_flags & cGLReplayerVerboseMode)
528 vogl_debug_printf("%s: Waiting for window to resize to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
530 return cStatusResizeWindow;
533 //----------------------------------------------------------------------------------------------------------------------
534 // vogl_replayer::clear_pending_window_resize
535 //----------------------------------------------------------------------------------------------------------------------
536 void vogl_gl_replayer::clear_pending_window_resize()
540 m_pending_window_resize_width = 0;
541 m_pending_window_resize_height = 0;
542 m_pending_window_resize_attempt_counter = 0;
545 //----------------------------------------------------------------------------------------------------------------------
546 // vogl_replayer::process_frame_check_for_pending_window_resize
547 //----------------------------------------------------------------------------------------------------------------------
548 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame_check_for_pending_window_resize()
552 const uint cMaxSecsToWait = 5;
554 if (!get_has_pending_window_resize())
557 if (m_pending_window_resize_attempt_counter >= cMaxSecsToWait)
559 vogl_warning_printf("Waited too long for window to resize to %ux%u, giving up and continuing replay\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
561 clear_pending_window_resize();
566 uint win_width = 0, win_height = 0;
567 m_pWindow->get_actual_dimensions(win_width, win_height);
569 if ((win_width != get_pending_window_resize_width()) ||
570 (win_height != get_pending_winow_resize_height()))
572 if (m_time_since_pending_window_resize.get_elapsed_secs() < 1.0f)
574 // sleep 1ms, then retry
576 return cStatusResizeWindow;
579 // What could possibly go wrong?
580 m_pending_window_resize_attempt_counter++;
581 if (m_pending_window_resize_attempt_counter < cMaxSecsToWait)
583 m_pWindow->resize(get_pending_window_resize_width(), get_pending_winow_resize_height());
585 m_time_since_pending_window_resize.start();
587 vogl_warning_printf("Waiting up to 5 secs for window to resize to %ux%u\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
588 return cStatusResizeWindow;
592 clear_pending_window_resize();
593 m_pWindow->update_dimensions();
598 //----------------------------------------------------------------------------------------------------------------------
599 // vogl_replayer::destroy_pending_snapshot
600 //----------------------------------------------------------------------------------------------------------------------
601 void vogl_gl_replayer::destroy_pending_snapshot()
605 if (m_pPending_snapshot)
607 if (m_delete_pending_snapshot_after_applying)
609 // Ensure the snapshot cache can't be pointing to the snapshot, just to be safe.
610 // TODO: Make this a real class damn it.
611 for (uint i = 0; i < m_snapshots.size(); i++)
613 if (m_snapshots[i].m_pSnapshot == m_pPending_snapshot)
615 m_snapshots.erase(i);
620 vogl_delete(const_cast<vogl_gl_state_snapshot *>(m_pPending_snapshot));
623 m_pPending_snapshot = NULL;
626 m_delete_pending_snapshot_after_applying = false;
629 //----------------------------------------------------------------------------------------------------------------------
630 // vogl_replayer::check_gl_error
631 // Returns *true* on error, just like vogl_check_gl_error()
632 //----------------------------------------------------------------------------------------------------------------------
633 bool vogl_gl_replayer::check_gl_error_internal(bool quietly, const char *pFile, uint line, const char *pFunc)
640 // http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
641 // "Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
642 GLenum gl_err = GL_ENTRYPOINT(glGetError)();
643 if (gl_err == GL_NO_ERROR)
648 process_entrypoint_warning("%s: GL error: 0x%08X (%u): %s (Called from File: %s Line: %u Func: %s)\n", VOGL_METHOD_NAME, gl_err, gl_err, g_gl_enums.find_name("ErrorCode", gl_err), pFile ? pFile : "?", line, pFunc ? pFunc : "?");
657 //----------------------------------------------------------------------------------------------------------------------
658 // vogl_replayer::clear_contexts
659 //----------------------------------------------------------------------------------------------------------------------
660 void vogl_gl_replayer::clear_contexts()
664 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
666 context_state *pContext_state = it->second;
668 vogl_delete(pContext_state);
673 m_cur_trace_context = 0;
674 m_cur_replay_context = NULL;
675 m_pCur_context_state = NULL;
678 //----------------------------------------------------------------------------------------------------------------------
679 // vogl_replayer::destroy_contexts
680 //----------------------------------------------------------------------------------------------------------------------
681 void vogl_gl_replayer::destroy_contexts()
685 if ((m_contexts.size()) && (m_pWindow->get_display()) && (GL_ENTRYPOINT(glXMakeCurrent)) && (GL_ENTRYPOINT(glXDestroyContext)))
687 GL_ENTRYPOINT(glXMakeCurrent)(m_pWindow->get_display(), (GLXDrawable)NULL, NULL);
689 vogl::vector<context_state *> contexts_to_destroy;
690 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
691 contexts_to_destroy.push_back(it->second);
693 // Delete "tail" contexts (ones that are not referenced by any other context) in sharegroups first.
694 while (contexts_to_destroy.size())
696 for (int i = 0; i < static_cast<int>(contexts_to_destroy.size()); i++)
698 context_state *pContext_state = contexts_to_destroy[i];
700 vogl_trace_ptr_value trace_context = pContext_state->m_context_desc.get_trace_context();
702 bool skip_context = false;
703 for (int j = 0; j < static_cast<int>(contexts_to_destroy.size()); j++)
708 if (contexts_to_destroy[j]->m_context_desc.get_trace_share_context() == trace_context)
718 // This context may have been the sharegroup's root and could have been already deleted.
719 if (!pContext_state->m_deleted)
721 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), pContext_state->m_replay_context);
724 contexts_to_destroy.erase(i);
733 //----------------------------------------------------------------------------------------------------------------------
734 // vogl_replayer::define_new_context
735 //----------------------------------------------------------------------------------------------------------------------
736 vogl_gl_replayer::context_state *vogl_gl_replayer::define_new_context(
737 vogl_trace_context_ptr_value trace_context, GLXContext replay_context, vogl_trace_context_ptr_value trace_share_context, GLboolean direct, gl_entrypoint_id_t creation_func, const int *pAttrib_list, uint attrib_list_size)
741 if ((!trace_context) || (!replay_context))
747 context_state *pContext_state = vogl_new(context_state, *this);
749 pContext_state->m_trace_context = trace_context;
750 pContext_state->m_replay_context = replay_context;
752 pContext_state->m_context_desc.init(creation_func, direct, trace_context, trace_share_context, vogl_context_attribs(pAttrib_list, attrib_list_size));
754 if (trace_share_context)
756 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
758 if (trace_share_context == it->first)
760 context_state *pShare_context = it->second;
761 while (!pShare_context->is_root_context())
762 pShare_context = pShare_context->m_pShared_state;
764 pContext_state->m_pShared_state = pShare_context;
765 pContext_state->m_pShared_state->m_ref_count++;
771 if (!pContext_state->m_pShared_state)
773 process_entrypoint_error("%s: Unable to find trace share context handle 0x%" PRIX64 "!\n", VOGL_METHOD_NAME, trace_share_context);
777 m_contexts.insert(trace_context, pContext_state);
779 return pContext_state;
782 //----------------------------------------------------------------------------------------------------------------------
783 // vogl_replayer::remap_context
784 //----------------------------------------------------------------------------------------------------------------------
785 GLXContext vogl_gl_replayer::remap_context(vogl_trace_context_ptr_value trace_context)
792 context_hash_map::iterator it = m_contexts.find(trace_context);
793 return (it == m_contexts.end()) ? NULL : it->second->m_replay_context;
796 //----------------------------------------------------------------------------------------------------------------------
797 // vogl_replayer::destroy_context
798 //----------------------------------------------------------------------------------------------------------------------
799 bool vogl_gl_replayer::destroy_context(vogl_trace_context_ptr_value trace_context)
803 VOGL_ASSERT(trace_context);
805 context_hash_map::iterator it = m_contexts.find(trace_context);
806 if (it == m_contexts.end())
809 context_state *pContext_state = it->second;
810 VOGL_ASSERT(pContext_state->m_ref_count >= 1);
811 VOGL_ASSERT(!pContext_state->m_deleted);
813 if (pContext_state->is_share_context())
815 VOGL_ASSERT(pContext_state->m_ref_count == 1);
817 context_state *pShare_context = pContext_state->m_pShared_state;
818 VOGL_ASSERT(pShare_context->m_ref_count >= 1);
820 pShare_context->m_ref_count--;
821 if (!pShare_context->m_ref_count)
823 VOGL_ASSERT(pShare_context->m_deleted);
825 vogl_trace_context_ptr_value trace_share_context = pShare_context->m_context_desc.get_trace_context();
827 vogl_delete(pShare_context);
829 bool removed = m_contexts.erase(trace_share_context);
830 VOGL_NOTE_UNUSED(removed);
831 VOGL_ASSERT(removed);
834 vogl_delete(pContext_state);
836 bool removed = m_contexts.erase(trace_context);
837 VOGL_NOTE_UNUSED(removed);
838 VOGL_ASSERT(removed);
842 pContext_state->m_deleted = true;
843 pContext_state->m_ref_count--;
845 if (!pContext_state->m_ref_count)
849 vogl_delete(pContext_state);
851 bool removed = m_contexts.erase(trace_context);
852 VOGL_NOTE_UNUSED(removed);
853 VOGL_ASSERT(removed);
860 //----------------------------------------------------------------------------------------------------------------------
861 // vogl_replayer::set_client_side_array_data
862 // glVertexPointer, glNormalPointer, etc. client side data
863 //----------------------------------------------------------------------------------------------------------------------
864 bool vogl_gl_replayer::set_client_side_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
868 // TODO: Add early out
869 GLint prev_client_active_texture = 0;
870 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
872 const uint tex_coords = math::minimum<uint>(m_pCur_context_state->m_context_info.is_core_profile() ? m_pCur_context_state->m_context_info.get_max_texture_units() : m_pCur_context_state->m_context_info.get_max_texture_coords(), VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS);
874 for (uint client_array_iter = 0; client_array_iter < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_array_iter++)
876 const vogl_client_side_array_desc_t &desc = g_vogl_client_side_array_descs[client_array_iter];
878 const bool is_texcoord_array = (client_array_iter == vogl_texcoord_pointer_array_id);
881 uint base_key_index = 0x1000 + client_array_iter;
883 // Special case texcoord pointers, which are accessed via the client active texture.
884 if (is_texcoord_array)
887 base_key_index = 0x2000;
890 for (uint inner_iter = 0; inner_iter < n; inner_iter++)
892 uint key_index = base_key_index + inner_iter;
894 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(key_index));
895 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
899 if (is_texcoord_array)
901 GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + inner_iter);
904 GLboolean is_enabled = GL_ENTRYPOINT(glIsEnabled)(desc.m_is_enabled);
909 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_binding, &binding);
914 GL_ENTRYPOINT(glGetPointerv)(desc.m_get_pointer, &ptr);
918 uint8_vec &array_data = is_texcoord_array ? m_client_side_texcoord_data[inner_iter] : m_client_side_array_data[client_array_iter];
919 if (ptr != array_data.get_ptr())
925 GLint type = GL_BOOL;
928 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_type, &type);
932 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_stride, &stride);
937 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_size, &size);
940 uint type_size = vogl_get_gl_type_size(type);
943 process_entrypoint_error("%s: Can't determine type size of enabled client side array set by func %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
947 if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointerEXT) ||
948 (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointerEXT) ||
949 (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointerEXT))
953 else if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointerEXT))
957 else if ((size < 1) && (size > 4))
959 process_entrypoint_error("%s: Size of client side array set by func %s must be between 1 and 4\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
964 stride = type_size * size;
966 uint first_vertex_ofs = (start + basevertex) * stride;
967 uint last_vertex_ofs = (end + basevertex) * stride;
968 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
969 uint total_data_size = last_vertex_ofs + stride;
974 process_entrypoint_error("%s: Failed finding client side vertex data blob set by func %s \n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
980 if (vertex_data_size != pVertex_blob->size())
982 process_entrypoint_error("%s: %s will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, vertex_data_size, pVertex_blob->size());
983 temp_blob = *pVertex_blob;
984 temp_blob.resize(vertex_data_size);
985 pVertex_blob = &temp_blob;
988 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
989 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
990 if (bytes_to_copy != pVertex_blob->size())
992 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
993 process_entrypoint_error("%s: %s accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, first_vertex_ofs + total_data_size);
996 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= array_data.size());
998 memcpy(array_data.get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1002 GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
1007 //----------------------------------------------------------------------------------------------------------------------
1008 // vogl_replayer::set_client_side_vertex_attrib_array_data
1009 // glVertexAttrib client side data
1010 //----------------------------------------------------------------------------------------------------------------------
1011 bool vogl_gl_replayer::set_client_side_vertex_attrib_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
1015 // TODO: Add early out
1017 for (int vertex_attrib_index = 0; vertex_attrib_index < static_cast<int>(m_pCur_context_state->m_context_info.get_max_vertex_attribs()); vertex_attrib_index++)
1019 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(vertex_attrib_index));
1021 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
1026 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1031 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &cur_buf);
1035 GLvoid *attrib_ptr = NULL;
1036 GL_ENTRYPOINT(glGetVertexAttribPointerv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib_ptr);
1040 if (attrib_ptr != m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr())
1046 GLint attrib_size = 0;
1047 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib_size);
1049 GLint attrib_type = 0;
1050 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib_type);
1052 GLint attrib_stride = 0;
1053 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib_stride);
1058 process_entrypoint_error("%s: Failed finding client side vertex data blob for generic vertex attrib %u\n", VOGL_METHOD_NAME, vertex_attrib_index);
1064 if ((attrib_size != GL_BGRA) && (attrib_size < 1) && (attrib_size > 4))
1066 process_entrypoint_error("%s: Enabled vertex attribute index %i has invalid size 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_size);
1069 if ((attrib_size >= 1) && (attrib_size <= 4))
1070 num_comps = attrib_size;
1072 uint type_size = vogl_get_gl_type_size(attrib_type);
1075 process_entrypoint_error("%s: Vertex attribute index %i has unsupported type 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_type);
1079 uint stride = attrib_stride ? attrib_stride : (type_size * num_comps);
1081 uint first_vertex_ofs = (start + basevertex) * stride;
1082 uint last_vertex_ofs = (end + basevertex) * stride;
1083 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
1084 uint total_data_size = last_vertex_ofs + stride;
1086 uint8_vec temp_blob;
1087 if (vertex_data_size != pVertex_blob->size())
1089 process_entrypoint_error("%s: Vertex attribute index %i will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, vertex_attrib_index, vertex_data_size, pVertex_blob->size());
1090 temp_blob = *pVertex_blob;
1091 temp_blob.resize(vertex_data_size);
1092 pVertex_blob = &temp_blob;
1095 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
1096 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
1097 if (bytes_to_copy != pVertex_blob->size())
1099 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
1100 process_entrypoint_error("%s: Vertex attribute index %i accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, vertex_attrib_index, first_vertex_ofs + total_data_size);
1103 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= m_client_side_vertex_attrib_data[vertex_attrib_index].size());
1105 memcpy(m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1111 //----------------------------------------------------------------------------------------------------------------------
1112 // vogl_replayer::draw_elements_client_side_array_setup
1113 //----------------------------------------------------------------------------------------------------------------------
1114 bool vogl_gl_replayer::draw_elements_client_side_array_setup(
1120 vogl_trace_ptr_value trace_indices_ptr_value, const GLvoid *&pIndices,
1122 bool has_valid_start_end,
1127 VOGL_NOTE_UNUSED(mode);
1131 GLuint element_array_buffer = 0;
1132 uint index_size = 0;
1135 index_size = vogl_get_gl_type_size(type);
1138 process_entrypoint_error("%s: Invalid type parameter 0x%08X\n", VOGL_METHOD_NAME, type);
1142 element_array_buffer = vogl_get_bound_gl_buffer(GL_ELEMENT_ARRAY_BUFFER);
1143 if (element_array_buffer)
1145 // trace_indices_ptr_value is actually an offset into the buffer, not a real trace ptr
1146 pIndices = reinterpret_cast<GLvoid *>(trace_indices_ptr_value);
1152 process_entrypoint_warning("%s: count parameter is <= 0 (%i)\n", VOGL_METHOD_NAME, count);
1156 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
1159 if ((indexed) && (!element_array_buffer) && (trace_indices_ptr_value))
1161 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob. Can't remap indices pointer!\n", VOGL_METHOD_NAME);
1162 if (trace_indices_ptr_value)
1164 // We can't remap the pointer to valid memory, so give up.
1169 // TODO: Check for client side array usage but no data in blob (which would be a desync or error)
1173 // TODO: If a VAO is bound, client side data isn't supported according to this:
1174 // http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
1176 //GLint current_vertex_array_binding = 0;
1177 //ACTUAL_GL_ENTRYPOINT(glGetIntegerv)(GL_VERTEX_ARRAY_BINDING, ¤t_vertex_array_binding);
1179 if ((indexed) && (!element_array_buffer))
1181 const uint8_vec *pIndices_vec = map.get_blob(string_hash("indices"));
1184 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob\n", VOGL_METHOD_NAME);
1188 pIndices = pIndices_vec->get_ptr();
1191 process_entrypoint_error("%s: No element array buffer is bound, but key value map has an empty indices blob\n", VOGL_METHOD_NAME);
1195 if ((pIndices_vec->size() / index_size) != static_cast<uint>(count))
1197 process_entrypoint_error("%s: Client side index data blob stored in packet is too small (wanted %u indices, got %u indices)\n", VOGL_METHOD_NAME, count, pIndices_vec->size() / index_size);
1202 if ((indexed) && (!has_valid_start_end))
1204 uint total_index_data_size = count * index_size;
1206 const uint8 *pIndices_to_scan = static_cast<const uint8 *>(pIndices);
1208 if (element_array_buffer)
1210 if (m_index_data.size() < total_index_data_size)
1211 m_index_data.resize(total_index_data_size);
1213 pIndices_to_scan = m_index_data.get_ptr();
1217 GL_ENTRYPOINT(glGetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)pIndices, total_index_data_size, m_index_data.get_ptr());
1219 if (check_gl_error())
1221 process_entrypoint_warning("%s: GL error while trying to retrieve index buffer data\n", VOGL_METHOD_NAME);
1223 memset(m_index_data.get_ptr(), 0, total_index_data_size);
1227 start = cUINT32_MAX;
1230 for (int i = 0; i < count; i++)
1234 if (type == GL_UNSIGNED_BYTE)
1235 v = pIndices_to_scan[i];
1236 else if (type == GL_UNSIGNED_SHORT)
1237 v = reinterpret_cast<const uint16 *>(pIndices_to_scan)[i];
1238 else if (type == GL_UNSIGNED_INT)
1239 v = reinterpret_cast<const uint32 *>(pIndices_to_scan)[i];
1242 process_entrypoint_error("%s: Invalid index type\n", VOGL_METHOD_NAME);
1246 start = math::minimum(start, v);
1247 end = math::maximum(end, v);
1250 has_valid_start_end = true;
1253 if (!set_client_side_array_data(map, start, end, basevertex))
1256 if (!set_client_side_vertex_attrib_array_data(map, start, end, basevertex))
1262 //----------------------------------------------------------------------------------------------------------------------
1263 // vogl_replayer::determine_uniform_replay_location
1264 //----------------------------------------------------------------------------------------------------------------------
1265 GLint vogl_gl_replayer::determine_uniform_replay_location(GLuint trace_program, GLint trace_location)
1269 // Seems better to return -1 when we can't find the uniform (which can happen if the driver optimizes the program differently vs. tracing).
1270 // Otherwise, we can pass an invalid handle down to the driver and this will crash AMD's fglrx.
1271 //GLint replay_location = trace_location;
1272 GLint replay_location = -1;
1274 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1275 if (it == get_shared_state()->m_glsl_program_hash_map.end())
1277 process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1281 glsl_program_state &state = it->second;
1283 uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1284 if (loc_it == state.m_uniform_locations.end())
1286 process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1290 replay_location = loc_it->second;
1293 return replay_location;
1296 //----------------------------------------------------------------------------------------------------------------------
1297 // vogl_replayer::process_entrypoint_print_summary_context
1298 //----------------------------------------------------------------------------------------------------------------------
1299 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1303 if (!m_pCur_gl_packet)
1306 console::printf(msg_type, "While processing GL entrypoint packet func %s, frame %u, swaps %u, GL call counter %" PRIu64 ", packet start trace context 0x%" PRIX64 ", cur trace context 0x%" PRIX64 ", trace thread 0x%" PRIX64 ":\n",
1307 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1308 m_frame_index, m_total_swaps,
1309 m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1310 m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1311 m_cur_trace_context,
1312 m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1315 dynamic_string_array backtrace;
1316 if (get_printable_backtrace(backtrace))
1318 console::printf("Backtrace:\n");
1319 for (uint i = 0; i < backtrace.size(); i++)
1320 console::printf("%s\n", backtrace[i].get_ptr());
1325 //----------------------------------------------------------------------------------------------------------------------
1326 // vogl_replayer::print_detailed_context
1327 //----------------------------------------------------------------------------------------------------------------------
1328 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1334 vogl_loose_file_blob_manager blob_file_manager;
1335 blob_file_manager.init(cBMFWritable);
1337 vogl_trace_packet::json_serialize_params serialize_params;
1338 serialize_params.m_output_basename = "replay_error";
1339 serialize_params.m_cur_frame = m_frame_index;
1340 serialize_params.m_blob_file_size_threshold = 1024;
1341 serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1342 m_pCur_gl_packet->json_serialize(node, serialize_params);
1344 dynamic_string node_str;
1345 node.serialize(node_str, true, 0);
1346 console::printf(msg_type, "Packet at call counter %" PRIu64 " as JSON:\n%s\n", m_pCur_gl_packet->get_entrypoint_packet().m_call_counter, node_str.get_ptr());
1349 //----------------------------------------------------------------------------------------------------------------------
1350 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1351 //----------------------------------------------------------------------------------------------------------------------
1352 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1356 if (!m_pCur_gl_packet)
1359 dump_packet_as_func_call(*m_pCur_gl_packet);
1361 if (!(m_flags & cGLReplayerDumpPacketsOnError))
1364 print_detailed_context(msg_type);
1367 //----------------------------------------------------------------------------------------------------------------------
1368 // vogl_replayer::process_entrypoint_info
1369 //----------------------------------------------------------------------------------------------------------------------
1370 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1374 process_entrypoint_print_summary_context(cInfoConsoleMessage);
1377 va_start(args, pFmt);
1378 console::vprintf(cInfoConsoleMessage, pFmt, args);
1381 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1384 //----------------------------------------------------------------------------------------------------------------------
1385 // vogl_replayer::process_entrypoint_message
1386 //----------------------------------------------------------------------------------------------------------------------
1387 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1391 process_entrypoint_print_summary_context(cMessageConsoleMessage);
1394 va_start(args, pFmt);
1395 console::vprintf(cMessageConsoleMessage, pFmt, args);
1398 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1401 //----------------------------------------------------------------------------------------------------------------------
1402 // vogl_replayer::process_entrypoint_warning
1403 //----------------------------------------------------------------------------------------------------------------------
1404 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1408 process_entrypoint_print_summary_context(cWarningConsoleMessage);
1411 va_start(args, pFmt);
1412 console::vprintf(cWarningConsoleMessage, pFmt, args);
1415 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1418 //----------------------------------------------------------------------------------------------------------------------
1419 // vogl_replayer::process_entrypoint_error
1420 //----------------------------------------------------------------------------------------------------------------------
1421 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1425 process_entrypoint_print_summary_context(cErrorConsoleMessage);
1428 va_start(args, pFmt);
1429 console::vprintf(cErrorConsoleMessage, pFmt, args);
1432 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1435 //----------------------------------------------------------------------------------------------------------------------
1436 // vogl_replayer::switch_contexts
1437 //----------------------------------------------------------------------------------------------------------------------
1438 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1443 //if (m_pCur_gl_packet->get_call_counter() == 25583)
1444 // vogl_debug_break();
1446 //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1447 if (trace_context == m_cur_trace_context)
1450 if (m_flags & cGLReplayerDebugMode)
1452 process_entrypoint_message("%s: Forcing context switch via glXMakeCurrent, from current trace context 0x%" PRIX64 " to new context 0x%" PRIX64 "\n", VOGL_METHOD_NAME, cast_val_to_uint64(m_cur_trace_context), cast_val_to_uint64(trace_context));
1455 // pContext_state will be NULL if they are unmapping!
1456 context_state *pContext_state = get_trace_context_state(trace_context);
1457 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1459 const Display *dpy = m_pWindow->get_display();
1460 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1462 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1465 process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1466 return cStatusHardFailure;
1469 m_cur_trace_context = trace_context;
1470 m_cur_replay_context = replay_context;
1471 m_pCur_context_state = pContext_state;
1476 //----------------------------------------------------------------------------------------------------------------------
1477 // vogl_replayer::debug_callback_arb
1478 //----------------------------------------------------------------------------------------------------------------------
1479 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1483 VOGL_NOTE_UNUSED(length);
1485 char final_message[4096];
1487 context_state *pContext_state = (context_state *)(pUser_param);
1489 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1493 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1494 cast_val_to_uint64(pContext_state->m_trace_context), cast_val_to_uint64(pContext_state->m_replay_context), cast_val_to_uint64(pContext_state->m_last_call_counter), final_message);
1498 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1502 //----------------------------------------------------------------------------------------------------------------------
1503 // vogl_replayer::is_extension_supported
1504 //----------------------------------------------------------------------------------------------------------------------
1505 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1509 if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1511 return m_pCur_context_state->m_context_info.supports_extension(pExt);
1519 //----------------------------------------------------------------------------------------------------------------------
1520 // vogl_replayer::context_state::handle_context_made_current
1521 //----------------------------------------------------------------------------------------------------------------------
1522 bool vogl_gl_replayer::context_state::handle_context_made_current()
1526 if (m_has_been_made_current)
1529 VOGL_CHECK_GL_ERROR;
1531 m_has_been_made_current = true;
1533 if (!m_context_info.init(m_context_desc))
1535 vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1539 if (!m_context_info.get_max_vertex_attribs())
1541 vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1543 else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1545 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);
1549 if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1551 vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1554 // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1555 // TODO: All more object types
1556 vogl::vector<GLuint> dummy_handles(65536);
1558 GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1559 GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1560 GL_ENTRYPOINT(glGenLists)(8000);
1561 GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1563 GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1564 GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1565 GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1566 GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1567 GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1569 for (uint i = 0; i < 22000; i++)
1570 GL_ENTRYPOINT(glCreateProgram)();
1572 vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1575 VOGL_CHECK_GL_ERROR;
1580 //----------------------------------------------------------------------------------------------------------------------
1581 // vogl_replayer::handle_context_made_current
1582 //----------------------------------------------------------------------------------------------------------------------
1583 bool vogl_gl_replayer::handle_context_made_current()
1587 if (!m_pCur_context_state->handle_context_made_current())
1590 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")))
1592 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1593 GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1597 if (m_flags & cGLReplayerVerboseMode)
1599 vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1601 (uint64_t)m_cur_trace_context,
1602 (uint64_t)m_cur_replay_context,
1603 m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1609 //----------------------------------------------------------------------------------------------------------------------
1610 // vogl_replayer::dump_context_attrib_list
1611 //----------------------------------------------------------------------------------------------------------------------
1612 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1618 vogl_debug_printf("Attrib list is NULL\n");
1621 vogl_debug_printf("Context attribs:\n");
1628 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1632 uint key = pAttrib_list[ofs];
1639 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1643 uint value = pAttrib_list[ofs];
1646 vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1648 vogl_debug_printf("End of context attribs\n");
1651 //----------------------------------------------------------------------------------------------------------------------
1652 // vogl_replayer::find_attrib_key
1653 //----------------------------------------------------------------------------------------------------------------------
1654 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1659 while (ofs < attrib_list.size())
1661 int key = attrib_list[ofs];
1665 if (++ofs >= attrib_list.size())
1667 process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1671 if (key == key_to_find)
1679 //----------------------------------------------------------------------------------------------------------------------
1680 // vogl_replayer::create_context_attribs
1681 //----------------------------------------------------------------------------------------------------------------------
1682 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1683 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,
1684 const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1688 vogl::vector<int> temp_attrib_list;
1690 if ((pTrace_attrib_list) && (trace_attrib_list_size))
1692 temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1693 if (temp_attrib_list.back() != 0)
1695 process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1700 if (expecting_attribs)
1702 if (m_flags & cGLReplayerVerboseMode)
1703 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1706 temp_attrib_list.push_back(0);
1709 if (m_flags & cGLReplayerForceDebugContexts)
1711 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1712 int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1713 if (context_flags_ofs < 0)
1715 temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1716 temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1717 temp_attrib_list.push_back(0);
1719 if (m_flags & cGLReplayerVerboseMode)
1720 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);
1724 temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1726 if (m_flags & cGLReplayerVerboseMode)
1727 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1730 int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1731 int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1733 bool slammed_up_to_3_0 = false;
1734 if (context_major_version_ofs < 0)
1736 // 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).
1738 temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1739 temp_attrib_list.push_back(3);
1740 temp_attrib_list.push_back(0);
1742 slammed_up_to_3_0 = true;
1745 else if (temp_attrib_list[context_major_version_ofs] < 3)
1747 temp_attrib_list[context_major_version_ofs] = 3;
1749 slammed_up_to_3_0 = true;
1752 if (slammed_up_to_3_0)
1754 if (context_minor_version_ofs < 0)
1756 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1757 temp_attrib_list.push_back(0);
1758 temp_attrib_list.push_back(0);
1762 temp_attrib_list[context_minor_version_ofs] = 0;
1765 process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1769 const int *pAttrib_list = temp_attrib_list.get_ptr();
1770 const uint attrib_list_size = temp_attrib_list.size();
1772 if (m_flags & cGLReplayerVerboseMode)
1773 dump_context_attrib_list(pAttrib_list, attrib_list_size);
1775 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1776 if (!replay_context)
1780 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1781 return cStatusHardFailure;
1785 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1793 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1794 VOGL_NOTE_UNUSED(pContext_state);
1798 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1805 //----------------------------------------------------------------------------------------------------------------------
1806 // vogl_replayer::process_pending_make_current
1807 //----------------------------------------------------------------------------------------------------------------------
1808 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1812 if (!m_pending_make_current_packet.is_valid())
1815 vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1817 Bool trace_result = gl_packet.get_return_value<Bool>();
1819 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1820 VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1822 // pContext_state will be NULL if they are unmapping!
1823 vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1824 context_state *pContext_state = get_trace_context_state(trace_context);
1825 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1827 if ((trace_context) && (!replay_context))
1829 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1830 m_pending_make_current_packet.clear();
1831 return cStatusHardFailure;
1834 const Display *dpy = m_pWindow->get_display();
1835 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1837 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1842 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1843 m_pending_make_current_packet.clear();
1844 return cStatusHardFailure;
1848 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1853 m_cur_trace_context = trace_context;
1854 m_cur_replay_context = replay_context;
1855 m_pCur_context_state = pContext_state;
1859 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1862 if (m_cur_replay_context)
1864 int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1865 int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1866 int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1867 int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1868 int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1869 int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1871 if (!m_pCur_context_state->m_has_been_made_current)
1873 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1874 viewport_x, viewport_y,
1875 viewport_width, viewport_height,
1876 win_width, win_height);
1879 GLint cur_viewport[4];
1880 GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1882 uint cur_win_width = 0, cur_win_height = 0;
1883 m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1885 if (!m_pCur_context_state->m_has_been_made_current)
1887 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1888 cur_viewport[0], cur_viewport[1],
1889 cur_viewport[2], cur_viewport[3],
1890 cur_win_width, cur_win_height);
1893 if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1895 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1898 if (!handle_context_made_current())
1899 return cStatusHardFailure;
1903 m_last_processed_call_counter = gl_packet.get_call_counter();
1905 m_pending_make_current_packet.clear();
1910 //----------------------------------------------------------------------------------------------------------------------
1911 // vogl_process_internal_trace_command_ctypes_packet
1912 //----------------------------------------------------------------------------------------------------------------------
1913 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1917 // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1918 int num_trace_ctypes = kvm.get_int("num_ctypes");
1919 VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1921 // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1922 // This will need to be revisited once we port to other OS's.
1923 // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1924 for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1926 const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1928 uint base_index = ctype_iter << 8;
1929 dynamic_string name(kvm.get_string(base_index++));
1930 dynamic_string ctype(kvm.get_string(base_index++));
1931 int size = kvm.get_int(base_index++);
1932 uint loki_type_flags = kvm.get_uint(base_index++);
1933 bool is_pointer = kvm.get_bool(base_index++);
1934 bool is_opaque_pointer = kvm.get_bool(base_index++);
1935 bool is_pointer_diff = kvm.get_bool(base_index++);
1936 bool is_opaque_type = kvm.get_bool(base_index++);
1938 VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1939 VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1940 if (!desc.m_is_opaque_type)
1942 VOGL_VERIFY(size == desc.m_size);
1945 const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1946 VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1948 VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1949 VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1950 VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1951 VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1957 //----------------------------------------------------------------------------------------------------------------------
1958 // vogl_replayer::process_internal_trace_command
1959 //----------------------------------------------------------------------------------------------------------------------
1960 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1964 VOGL_NOTE_UNUSED(gl_packet);
1966 GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1967 GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1968 VOGL_NOTE_UNUSED(size);
1969 vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1970 VOGL_NOTE_UNUSED(trace_data_ptr_value);
1972 vogl_gl_replayer::status_t status = cStatusOK;
1976 case cITCRDemarcation:
1980 case cITCRKeyValueMap:
1982 const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
1984 dynamic_string cmd_type(kvm.get_string("command_type"));
1985 if (cmd_type == "state_snapshot")
1987 dynamic_string text_id(kvm.get_string("id"));
1988 dynamic_string binary_id(kvm.get_string("binary_id"));
1989 if (text_id.is_empty() && binary_id.is_empty())
1991 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());
1992 return cStatusHardFailure;
1995 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
1997 // TODO: Make a 1st class snapshot cache class
1998 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
1999 vogl_gl_state_snapshot *pSnapshot = NULL;
2000 if (m_flags & cGLReplayerSnapshotCaching)
2002 for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2004 if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2006 pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2009 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2010 m_snapshots.erase(snapshot_index);
2011 m_snapshots.insert(0, cache_entry);
2020 timed_scope ts("Deserialize snapshot time");
2022 if (!m_pBlob_manager)
2024 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2025 return cStatusHardFailure;
2028 uint8_vec snapshot_data;
2030 if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2032 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2033 return cStatusHardFailure;
2036 vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2041 if (id_to_use == text_id)
2042 success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2044 success = doc.binary_deserialize(snapshot_data);
2045 if (!success || (!doc.get_root()))
2047 process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2048 return cStatusHardFailure;
2051 pSnapshot = vogl_new(vogl_gl_state_snapshot);
2052 if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2054 vogl_delete(pSnapshot);
2057 process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2058 return cStatusHardFailure;
2061 if (m_flags & cGLReplayerSnapshotCaching)
2063 snapshot_cache_entry new_cache_entry;
2064 new_cache_entry.m_name = id_to_use;
2065 new_cache_entry.m_pSnapshot = pSnapshot;
2066 m_snapshots.insert(0, new_cache_entry);
2068 // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2069 while (m_snapshots.size() > 3)
2071 vogl_delete(m_snapshots.back().m_pSnapshot);
2072 m_snapshots.resize(m_snapshots.size() - 1);
2077 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2079 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2081 if (m_flags & cGLReplayerSnapshotCaching)
2083 VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2085 vogl_delete(m_snapshots[0].m_pSnapshot);
2086 m_snapshots.erase(0U);
2089 if (m_flags & cGLReplayerSnapshotCaching)
2091 vogl_delete(pSnapshot);
2095 process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2099 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2101 else if (cmd_type == "ctypes")
2103 m_ctypes_packet = *m_pCur_gl_packet;
2105 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2106 return cStatusHardFailure;
2108 else if (cmd_type == "entrypoints")
2114 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2120 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2128 //----------------------------------------------------------------------------------------------------------------------
2129 // vogl_replayer::check_program_binding_shadow
2130 //----------------------------------------------------------------------------------------------------------------------
2131 bool vogl_gl_replayer::check_program_binding_shadow()
2135 if (!m_pCur_context_state)
2138 // Make sure shadow is good
2139 GLint actual_current_replay_program = 0;
2140 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2143 if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2146 // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2147 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2148 if ((!check_gl_error()) && (is_still_program))
2150 GLint marked_for_deletion = GL_FALSE;
2151 GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2153 if ((!check_gl_error()) && (marked_for_deletion))
2161 //----------------------------------------------------------------------------------------------------------------------
2162 // vogl_replayer::handle_use_program
2163 //----------------------------------------------------------------------------------------------------------------------
2164 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2168 // 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.
2169 check_program_binding_shadow();
2171 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2172 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2173 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2175 // For safety, absorb any previous error.
2178 GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2179 GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2181 bool prev_is_program = false;
2182 GLint prev_link_status = false;
2183 GLint prev_is_marked_for_deletion = false;
2184 vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2186 if ((prev_replay_program) && (replay_handle != prev_replay_program))
2188 prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2189 check_gl_error_quietly();
2191 if (prev_is_program)
2193 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2194 check_gl_error_quietly();
2196 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2197 check_gl_error_quietly();
2199 if (prev_is_marked_for_deletion)
2201 // 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.
2202 GLint num_attached_shaders = 0;
2203 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2204 check_gl_error_quietly();
2206 if (num_attached_shaders)
2208 prev_attached_replay_shaders.resize(num_attached_shaders);
2210 GLsizei actual_count = 0;
2211 GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2212 check_gl_error_quietly();
2214 VOGL_ASSERT(actual_count == num_attached_shaders);
2220 if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2221 GL_ENTRYPOINT(glUseProgram)(replay_handle);
2223 GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2225 // Can't shadow if glUseProgram failed.
2226 if (check_gl_error())
2229 if ((prev_replay_program) && (prev_replay_program != replay_handle))
2231 bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2232 if (!is_prev_still_program)
2234 VOGL_ASSERT(prev_is_program);
2235 VOGL_ASSERT(prev_is_marked_for_deletion);
2237 // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2238 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2239 VOGL_ASSERT(was_deleted);
2240 VOGL_NOTE_UNUSED(was_deleted);
2242 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2243 VOGL_ASSERT(was_deleted);
2245 was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2246 if ((prev_link_status) && (!was_deleted))
2251 for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2253 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2255 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2256 check_gl_error_quietly();
2258 if (is_still_shader)
2261 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2263 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2267 // The attached shader is now really dead.
2268 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2269 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2271 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);
2277 m_pCur_context_state->m_cur_replay_program = replay_handle;
2278 m_pCur_context_state->m_cur_trace_program = trace_handle;
2281 //----------------------------------------------------------------------------------------------------------------------
2282 // vogl_replayer::handle_delete_program
2283 //----------------------------------------------------------------------------------------------------------------------
2284 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2288 check_program_binding_shadow();
2290 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2292 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2293 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2294 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2296 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2297 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2299 if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2302 context_state *pContext = it->second;
2303 if (pContext->m_pShared_state == pContext_shareroot)
2305 if (pContext->m_cur_trace_program == trace_handle)
2307 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",
2308 VOGL_METHOD_NAME, trace_handle, replay_handle,
2309 cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2310 cast_val_to_uint64(it->first));
2315 bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2316 check_gl_error_quietly();
2318 vogl::growable_array<GLuint, 8> attached_replay_shaders;
2320 if ((is_program) && (replay_handle))
2322 GLint num_attached_shaders = 0;
2323 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2324 check_gl_error_quietly();
2326 if (num_attached_shaders)
2328 attached_replay_shaders.resize(num_attached_shaders);
2330 GLsizei actual_count = 0;
2331 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2332 check_gl_error_quietly();
2334 VOGL_ASSERT(actual_count == num_attached_shaders);
2338 GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2340 bool deletion_succeeded = !check_gl_error();
2341 if (!deletion_succeeded)
2343 VOGL_ASSERT(!is_program);
2345 process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2352 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2353 check_gl_error_quietly();
2355 GLint marked_for_deletion = 0;
2356 if (is_still_program)
2358 // It must still be bound to the context, or referred to in some other way that we don't know about.
2359 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2360 bool delete_status_check_succeeded = !check_gl_error_quietly();
2362 VOGL_VERIFY(delete_status_check_succeeded);
2363 VOGL_VERIFY(marked_for_deletion);
2365 else if (!is_still_program)
2367 VOGL_ASSERT(is_program);
2369 // The program is really gone now.
2370 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2371 VOGL_ASSERT(was_deleted);
2372 VOGL_NOTE_UNUSED(was_deleted);
2374 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2375 VOGL_ASSERT(was_deleted);
2377 get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2379 if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2381 // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2383 m_pCur_context_state->m_cur_replay_program = 0;
2384 m_pCur_context_state->m_cur_trace_program = 0;
2387 for (uint i = 0; i < attached_replay_shaders.size(); i++)
2389 GLuint replay_shader_handle = attached_replay_shaders[i];
2391 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2392 check_gl_error_quietly();
2394 if (is_still_shader)
2397 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2399 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2403 // The attached shader is now really dead.
2404 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2405 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2407 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);
2413 //----------------------------------------------------------------------------------------------------------------------
2414 // vogl_replayer::handle_delete_shader
2415 //----------------------------------------------------------------------------------------------------------------------
2416 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2420 check_program_binding_shadow();
2424 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2426 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2427 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2428 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2430 GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2432 bool deletion_succeeded = !check_gl_error();
2433 if (!deletion_succeeded)
2435 process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2442 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2443 check_gl_error_quietly();
2445 if (!is_still_shader)
2447 // The shader is really gone.
2448 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2449 VOGL_ASSERT(was_deleted);
2450 VOGL_NOTE_UNUSED(was_deleted);
2454 GLint marked_for_deletion = 0;
2455 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2456 check_gl_error_quietly();
2458 VOGL_VERIFY(marked_for_deletion);
2460 // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2461 // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2465 //----------------------------------------------------------------------------------------------------------------------
2466 // vogl_replayer::handle_detach_shader
2467 //----------------------------------------------------------------------------------------------------------------------
2468 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2470 GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2471 GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2473 GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2474 GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2478 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2480 GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2481 check_gl_error_quietly();
2483 GLint marked_for_deletion = 0;
2484 GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2485 check_gl_error_quietly();
2487 if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2488 GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2491 VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2492 GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2495 bool detach_failed = check_gl_error();
2497 GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2498 check_gl_error_quietly();
2502 if ((marked_for_deletion) && (was_shader) && (!is_shader))
2504 // The shader is really gone now.
2505 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2506 VOGL_ASSERT(was_deleted);
2507 VOGL_NOTE_UNUSED(was_deleted);
2512 //----------------------------------------------------------------------------------------------------------------------
2513 // vogl_gl_replayer::handle_link_program
2514 //----------------------------------------------------------------------------------------------------------------------
2515 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2519 GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2520 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2522 GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2526 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);
2529 const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2533 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);
2535 else if ((pDoc) && (!pDoc->is_object()))
2537 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);
2541 int trace_active_attributes = 0;
2542 int trace_active_uniforms = 0;
2543 int trace_active_uniform_blocks = 0;
2544 int trace_link_status = 1;
2546 VOGL_NOTE_UNUSED(trace_active_uniforms);
2547 VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2551 const json_node &doc_root = *pDoc->get_root();
2553 trace_link_status = doc_root.value_as_int("link_status");
2554 trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2555 trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2556 trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2558 const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2561 for (uint i = 0; i < pAttrib_node->size(); i++)
2563 const json_node *pAttrib = pAttrib_node->get_child(i);
2570 const char *pName = pAttrib->value_as_string_ptr("name");
2571 int attrib_loc = pAttrib->value_as_int("location", -1);
2573 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2575 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2576 GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2578 GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2585 const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2586 if (pOutputs_object)
2588 for (uint i = 0; i < pOutputs_object->size(); i++)
2590 const json_node *pOutput_node = pOutputs_object->get_child(i);
2594 dynamic_string name(pOutput_node->value_as_string("name"));
2595 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2598 int location = pOutput_node->value_as_int("location");
2599 int location_index = pOutput_node->value_as_int("location_index");
2601 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2603 GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2608 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);
2610 GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2617 GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2618 GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2621 const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2622 if (pTransform_feedback_varyings)
2624 dynamic_string_array names;
2626 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2628 const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2632 GLint index = pVarying_node->value_as_int("index");
2636 dynamic_string name(pVarying_node->value_as_string("name"));
2638 //GLsizei size(pVarying_node->value_as_int("size"));
2639 //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2641 names.ensure_element_is_valid(index);
2642 names[index] = name;
2645 vogl::vector<GLchar *> varyings(names.size());
2646 for (uint i = 0; i < names.size(); i++)
2647 varyings[i] = (GLchar *)(names[i].get_ptr());
2649 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2655 switch (entrypoint_id)
2657 case VOGL_ENTRYPOINT_glLinkProgram:
2659 GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2662 case VOGL_ENTRYPOINT_glLinkProgramARB:
2664 GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2667 case VOGL_ENTRYPOINT_glProgramBinary:
2669 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));
2681 GLint replay_link_status = 0;
2682 GLint replay_active_attributes = 0;
2683 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2685 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2688 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2693 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2696 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2700 if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2703 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2704 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));
2706 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);
2709 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);
2712 if ((pDoc) && (replay_link_status != trace_link_status))
2714 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);
2717 if (!replay_link_status)
2719 vogl::vector<GLchar> log;
2721 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2724 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2731 GLint actual_length = 0;
2732 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2739 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2746 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2751 if ((log.size()) && (log[0]))
2753 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());
2757 if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2759 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);
2762 const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2766 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2767 if (it == get_shared_state()->m_glsl_program_hash_map.end())
2768 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2769 glsl_program_state &prog_state = it->second;
2771 for (uint i = 0; i < pUniforms_node->size(); i++)
2773 const json_node *pUniform = pUniforms_node->get_child(i);
2780 const char *pName = pUniform->value_as_string_ptr("name");
2786 int trace_loc = pUniform->value_as_int("location");
2787 int trace_array_size = pUniform->value_as_int("size");
2788 //int trace_type = pUniform->value_as_int("type");
2790 VOGL_ASSERT(trace_array_size >= 1);
2792 if ((trace_loc < 0) || (trace_array_size <= 0))
2795 if (trace_array_size > 1)
2797 dynamic_string element_name;
2798 for (int i = 0; i < trace_array_size; i++)
2800 element_name = pName;
2801 int start_bracket_ofs = element_name.find_right('[');
2802 if (start_bracket_ofs >= 0)
2803 element_name.left(start_bracket_ofs);
2804 element_name.format_append("[%u]", i);
2806 GLint element_trace_loc = trace_loc + i;
2807 GLint element_replay_loc;
2808 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2809 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2811 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2814 if (element_replay_loc < 0)
2816 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);
2820 prog_state.m_uniform_locations.erase(element_trace_loc);
2821 prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2825 else if (trace_array_size == 1)
2828 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2829 replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2831 replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2836 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);
2840 prog_state.m_uniform_locations.erase(trace_loc);
2841 prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2848 //----------------------------------------------------------------------------------------------------------------------
2849 // vogl_gl_replayer::post_draw_call
2850 // Called after each draw call or blit.
2851 //----------------------------------------------------------------------------------------------------------------------
2852 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2856 if (m_pCur_context_state->m_inside_gl_begin)
2859 if (check_gl_error())
2860 return cStatusGLError;
2862 bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2864 if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2866 dump_current_shaders();
2869 if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2871 bool should_dump = false;
2873 if (m_dump_framebuffer_on_draw_frame_index != -1)
2875 if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2878 else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2880 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);
2889 dump_current_framebuffer();
2893 m_frame_draw_counter += is_draw;
2898 //----------------------------------------------------------------------------------------------------------------------
2899 // vogl_gl_replayer::dump_framebuffer
2900 //----------------------------------------------------------------------------------------------------------------------
2901 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)
2905 uint trace_read_framebuffer = 0;
2906 if (read_framebuffer)
2908 gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2909 if (it != get_context_state()->m_framebuffers.end())
2910 trace_read_framebuffer = it->second;
2913 uint trace_texture = replay_texture;
2916 if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2917 vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2923 if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2924 vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2927 m_screenshot_buffer.resize(width * height * 3);
2929 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);
2933 process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2937 size_t png_size = 0;
2938 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2940 dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2941 m_dump_framebuffer_on_draw_prefix.get_ptr(),
2942 (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2943 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2945 (unsigned long long)m_frame_draw_counter,
2947 trace_read_framebuffer,
2948 g_gl_enums.find_gl_name(read_buffer));
2950 if (internal_format != GL_NONE)
2952 screenshot_filename += "_";
2953 screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2956 if (orig_samples != 0)
2957 screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2959 screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2961 screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2963 screenshot_filename += ".png";
2965 file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2967 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2969 process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2974 vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2982 //----------------------------------------------------------------------------------------------------------------------
2983 // vogl_gl_replayer::dump_current_framebuffer
2984 //----------------------------------------------------------------------------------------------------------------------
2985 void vogl_gl_replayer::dump_current_framebuffer()
2989 uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
2991 uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
2992 if (!max_draw_buffers)
2994 process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
2998 //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
3000 vogl::vector<GLenum> draw_buffers(max_draw_buffers);
3001 for (uint i = 0; i < max_draw_buffers; i++)
3002 draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3004 if (!draw_framebuffer_binding)
3006 for (uint i = 0; i < max_draw_buffers; i++)
3007 if (draw_buffers[i] != GL_NONE)
3008 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3012 // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3013 vogl_framebuffer_state fbo_state;
3014 if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3016 process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3020 for (uint i = 0; i < draw_buffers.size(); i++)
3022 if (draw_buffers[i] == GL_NONE)
3025 const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3028 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);
3032 if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3034 else if (pAttachment->get_type() == GL_RENDERBUFFER)
3036 GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3040 vogl_renderbuffer_state rbo_state;
3041 if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3043 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3047 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))
3050 uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3051 uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3052 uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3053 GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3055 if ((!width) || (!height) || (!internal_format))
3057 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);
3063 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3065 GLuint temp_rbo = 0;
3066 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3072 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3075 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3078 GLuint temp_fbo = 0;
3079 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3082 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3085 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3088 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3089 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3092 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3095 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3098 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3100 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3103 // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3104 vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3106 GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3109 GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3111 if (!check_gl_error())
3112 dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3115 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);
3119 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3122 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3125 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3128 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3133 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3136 else if (pAttachment->get_type() == GL_TEXTURE)
3138 GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3141 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3145 GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3146 if (target == GL_NONE)
3148 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);
3152 if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3153 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3155 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))
3157 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);
3161 uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3162 uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3163 VOGL_NOTE_UNUSED(layer);
3165 GLint width = 0, height = 0, samples = 0;
3166 GLenum internal_format = GL_NONE;
3169 vogl_scoped_binding_state binding_saver;
3170 binding_saver.save_textures();
3172 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3175 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3178 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3181 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3184 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3186 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3191 if ((!width) || (!height))
3193 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);
3199 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3203 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3208 //----------------------------------------------------------------------------------------------------------------------
3209 // vogl_gl_replayer::dump_current_shaders
3210 //----------------------------------------------------------------------------------------------------------------------
3211 void vogl_gl_replayer::dump_current_shaders()
3215 if (!m_pCur_context_state)
3220 const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3222 // Get the current program.
3223 GLuint current_program = 0;
3224 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(¤t_program));
3227 VOGL_ASSERT(replay_program == current_program);
3229 if (!current_program)
3232 // Get the attached shaders.
3233 GLsizei attached_shader_count = -1;
3234 GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3237 if (!attached_shader_count)
3240 vogl::vector<GLuint> shaders(attached_shader_count);
3241 GLsizei actual_shader_count = 0;
3242 GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3243 attached_shader_count,
3244 &actual_shader_count,
3248 VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3250 vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3251 cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3252 replay_program, m_pCur_context_state->m_cur_trace_program,
3253 attached_shader_count);
3255 // Get source from shaders.
3256 vogl::vector<GLchar> source; // Shared buffer for each iteration.
3257 for (GLsizei i = 0; i < attached_shader_count; ++i)
3259 const GLuint shader = shaders[i];
3260 GLint shader_type = 0;
3261 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3264 vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3266 GLint source_length = -1; // Includes NUL terminator.
3267 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3270 VOGL_ASSERT(source_length > 0);
3272 source.resize(source_length);
3273 GLint actual_length = 0; // Excludes NUL terminator!
3274 GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3277 VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3278 vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3280 vogl_printf("========\n");
3283 //----------------------------------------------------------------------------------------------------------------------
3284 // vogl_gl_replayer::handle_ShaderSource
3285 // Handle ShaderSource and ShaderSourceARB.
3286 //----------------------------------------------------------------------------------------------------------------------
3287 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3289 const vogl_client_memory_array trace_strings_glchar_ptr_array,
3290 const GLint *pTrace_lengths)
3294 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3296 // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3297 const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3298 const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3300 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3301 (trace_strings_count != static_cast<uint>(count)))
3303 process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3304 VOGL_METHOD_NAME, count, trace_strings_count);
3305 return cStatusHardFailure;
3308 if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3310 process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3311 VOGL_METHOD_NAME, count, trace_lengths_count);
3312 return cStatusHardFailure;
3315 vogl::vector<const GLcharARB *> strings(count);
3316 vogl::vector<GLint> lengths(count);
3318 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3320 vogl::vector<uint8_vec> blobs(count);
3322 for (GLsizei i = 0; i < count; i++)
3325 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3326 (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3331 lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3333 key_value_map::const_iterator it = map.find(i);
3334 if (it == map.end())
3338 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3339 VOGL_METHOD_NAME, i);
3340 return cStatusHardFailure;
3345 const uint8_vec *pBlob = it->second.get_blob();
3348 process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3349 return cStatusHardFailure;
3353 uint8_vec &blob = blobs[i];
3355 if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3357 if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3359 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());
3360 lengths[i] = blob.size();
3365 if ((blob.size()) && (blob.back() != '\0'))
3367 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3369 blob.push_back('\0');
3372 VOGL_ASSERT(blob.size() &&
3373 (blob.back() == '\0') &&
3374 (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3377 strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3380 if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3382 GL_ENTRYPOINT(glShaderSource)(replay_object,
3384 trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3385 pTrace_lengths ? lengths.get_ptr() : NULL);
3389 GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3391 trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3392 pTrace_lengths ? lengths.get_ptr() : NULL);
3397 //----------------------------------------------------------------------------------------------------------------------
3398 // vogl_gl_replayer::display_list_bind_callback
3399 // handle is in the trace namespace
3400 //----------------------------------------------------------------------------------------------------------------------
3401 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3405 vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3407 if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3409 if ((handle) && (target != GL_NONE))
3411 // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3412 pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3417 // TODO - right now the display list whitelist doens't let anything else get bound.
3418 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);
3422 //----------------------------------------------------------------------------------------------------------------------
3423 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3424 //----------------------------------------------------------------------------------------------------------------------
3425 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...) \
3426 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3427 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3429 result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3431 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...) \
3432 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3433 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3434 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3435 result = GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3437 result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3439 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...) \
3440 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3441 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3443 GL_ENTRYPOINT(e1)(__VA_ARGS__);
3445 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...) \
3446 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3447 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3448 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3449 GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3451 GL_ENTRYPOINT(e2)(__VA_ARGS__);
3453 //----------------------------------------------------------------------------------------------------------------------
3454 // vogl_replayer::process_gl_entrypoint_packet
3455 // This will be called during replaying, or when building display lists during state restoring.
3456 //----------------------------------------------------------------------------------------------------------------------
3457 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3459 m_pCur_gl_packet = &trace_packet;
3461 status_t status = cStatusOK;
3463 if (m_pPending_snapshot)
3465 status = process_applying_pending_snapshot();
3466 if (status != cStatusOK)
3470 if (m_pending_make_current_packet.is_valid())
3472 status = process_pending_make_current();
3473 if (status != cStatusOK)
3477 const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3479 m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3481 status = process_gl_entrypoint_packet_internal(trace_packet);
3483 if (status != cStatusResizeWindow)
3484 m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3486 m_pCur_gl_packet = NULL;
3491 //----------------------------------------------------------------------------------------------------------------------
3492 // vogl_replayer::process_gl_entrypoint_packet_internal
3493 // This will be called during replaying, or when building display lists during state restoring.
3494 //----------------------------------------------------------------------------------------------------------------------
3495 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3499 m_at_frame_boundary = false;
3501 const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3502 const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3504 if (m_flags & cGLReplayerDebugMode)
3505 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3507 if (m_flags & cGLReplayerDebugMode)
3508 dump_packet_as_func_call(trace_packet);
3510 if (m_flags & cGLReplayerDumpAllPackets)
3511 print_detailed_context(cDebugConsoleMessage);
3513 if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3514 return process_internal_trace_command(gl_entrypoint_packet);
3516 status_t status = cStatusOK;
3518 if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3520 status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3521 if (status != cStatusOK)
3525 bool processed_glx_packet = true;
3526 switch (entrypoint_id)
3528 case VOGL_ENTRYPOINT_glXDestroyContext:
3530 const Display *dpy = m_pWindow->get_display();
3532 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3533 GLXContext replay_context = remap_context(trace_context);
3535 if ((trace_context) && (!replay_context))
3537 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3538 return cStatusHardFailure;
3541 if (trace_context == m_cur_trace_context)
3543 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3544 VOGL_METHOD_NAME, (uint64_t)trace_context);
3546 m_cur_trace_context = 0;
3547 m_cur_replay_context = 0;
3548 m_pCur_context_state = NULL;
3551 GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3553 destroy_context(trace_context);
3557 case VOGL_ENTRYPOINT_glXMakeCurrent:
3558 case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3560 Bool trace_result = trace_packet.get_return_value<Bool>();
3562 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3564 // pContext_state can be NULL!
3565 context_state *pContext_state = get_trace_context_state(trace_context);
3566 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3568 if ((trace_context) && (!replay_context))
3570 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3571 return cStatusHardFailure;
3574 int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3575 VOGL_NOTE_UNUSED(viewport_x);
3576 int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3577 VOGL_NOTE_UNUSED(viewport_y);
3578 int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3579 VOGL_NOTE_UNUSED(viewport_width);
3580 int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3581 VOGL_NOTE_UNUSED(viewport_height);
3582 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3583 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3585 // 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.
3586 if ((trace_context) && (trace_result))
3588 if ((win_width) && (win_height))
3590 if (!(m_flags & cGLReplayerLockWindowDimensions))
3592 if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3594 m_pending_make_current_packet = *m_pCur_gl_packet;
3596 status = trigger_pending_window_resize(win_width, win_height);
3598 vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3604 if (status != cStatusResizeWindow)
3606 const Display *dpy = m_pWindow->get_display();
3607 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3609 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3614 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3615 return cStatusHardFailure;
3619 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3624 m_cur_trace_context = trace_context;
3625 m_cur_replay_context = replay_context;
3626 m_pCur_context_state = pContext_state;
3630 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3634 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3635 viewport_x, viewport_y,
3636 viewport_width, viewport_height,
3637 win_width, win_height);
3640 if (m_cur_replay_context)
3642 if (!handle_context_made_current())
3643 return cStatusHardFailure;
3650 case VOGL_ENTRYPOINT_glXQueryVersion:
3652 int major = 0, minor = 0;
3653 Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3654 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,
3655 *trace_packet.get_param_client_memory<int>(1),
3656 *trace_packet.get_param_client_memory<int>(2),
3657 trace_packet.get_return_value<Bool>());
3661 case VOGL_ENTRYPOINT_glXChooseFBConfig:
3666 case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3671 case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3676 case VOGL_ENTRYPOINT_glXGetProcAddress:
3677 case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3679 const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3680 vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3682 void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3684 if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3686 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3687 (const char *)procName,
3688 (pFunc != NULL) ? "succeeded" : "failed",
3689 (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3694 case VOGL_ENTRYPOINT_glXCreateNewContext:
3696 Display *dpy = m_pWindow->get_display();
3697 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3698 int render_type = trace_packet.get_param_value<GLint>(2);
3700 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3701 GLXContext replay_share_context = remap_context(trace_share_context);
3703 if ((trace_share_context) && (!replay_share_context))
3705 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3708 Bool direct = trace_packet.get_param_value<Bool>(4);
3709 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3711 if (m_flags & cGLReplayerForceDebugContexts)
3713 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);
3715 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3716 if (status != cStatusOK)
3721 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3723 if (!replay_context)
3727 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3728 return cStatusHardFailure;
3732 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3740 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3741 VOGL_NOTE_UNUSED(pContext_state);
3745 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3752 case VOGL_ENTRYPOINT_glXCreateContext:
3754 Display *dpy = m_pWindow->get_display();
3756 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3757 GLXContext replay_share_context = remap_context(trace_share_context);
3759 if ((trace_share_context) && (!replay_share_context))
3761 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3764 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3765 Bool direct = trace_packet.get_param_value<Bool>(3);
3766 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3768 if (m_flags & cGLReplayerForceDebugContexts)
3770 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3771 if (status != cStatusOK)
3776 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3778 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3780 if (!replay_context)
3784 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3785 return cStatusHardFailure;
3789 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3797 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3798 VOGL_NOTE_UNUSED(pContext_state);
3802 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3809 case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3811 Display *dpy = m_pWindow->get_display();
3812 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3814 vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3815 GLXContext replay_share_context = remap_context(trace_share_context);
3817 if ((trace_share_context) && (!replay_share_context))
3819 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3822 Bool direct = trace_packet.get_param_value<Bool>(3);
3823 const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3824 const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3826 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3828 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3829 if (status != cStatusOK)
3834 case VOGL_ENTRYPOINT_glXSwapBuffers:
3836 check_program_binding_shadow();
3838 if (m_flags & cGLReplayerLowLevelDebugMode)
3840 if (!validate_program_and_shader_handle_tables())
3841 vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3842 if (!validate_textures())
3843 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3846 const Display *dpy = m_pWindow->get_display();
3847 GLXDrawable drawable = m_pWindow->get_xwindow();
3849 if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3851 snapshot_backbuffer();
3854 if (m_dump_frontbuffer_filename.has_content())
3856 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3857 m_dump_frontbuffer_filename.clear();
3860 GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3862 if (m_swap_sleep_time)
3863 vogl_sleep(m_swap_sleep_time);
3865 status = cStatusNextFrame;
3867 m_at_frame_boundary = true;
3869 if (m_flags & cGLReplayerDebugMode)
3871 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);
3877 m_frame_draw_counter = 0;
3879 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3880 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3881 if ((win_width) && (win_height))
3883 if (!(m_flags & cGLReplayerLockWindowDimensions))
3885 if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3887 // TODO: This resize might need to be deferred until the window system actually resizes the window.
3888 //m_pWindow->resize(win_width, win_height);
3889 trigger_pending_window_resize(win_width, win_height);
3891 vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3898 case VOGL_ENTRYPOINT_glXWaitX:
3900 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3902 VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3906 case VOGL_ENTRYPOINT_glXWaitGL:
3908 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3910 VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3914 case VOGL_ENTRYPOINT_glXIsDirect:
3916 const Display *dpy = m_pWindow->get_display();
3918 vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3919 GLXContext replay_context = remap_context(trace_context);
3921 Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3922 Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3924 if (replay_is_direct != trace_is_direct)
3926 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3931 case VOGL_ENTRYPOINT_glXGetCurrentContext:
3933 GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3934 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3936 if ((replay_context != 0) != (trace_context != 0))
3938 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);
3943 case VOGL_ENTRYPOINT_glXCreateWindow:
3944 case VOGL_ENTRYPOINT_glXDestroyWindow:
3945 case VOGL_ENTRYPOINT_glXChooseVisual:
3946 case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3947 case VOGL_ENTRYPOINT_glXQueryDrawable:
3948 case VOGL_ENTRYPOINT_glXQueryExtension:
3949 case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3950 case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3951 case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3952 case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3953 case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3954 case VOGL_ENTRYPOINT_glXQueryContext:
3955 case VOGL_ENTRYPOINT_glXGetClientString:
3956 case VOGL_ENTRYPOINT_glXGetConfig:
3957 case VOGL_ENTRYPOINT_glXGetFBConfigs:
3964 processed_glx_packet = false;
3969 if (processed_glx_packet)
3971 // TODO: Check for GLX errors?
3975 if (!m_cur_replay_context)
3977 process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
3978 return cStatusSoftFailure;
3981 VOGL_ASSERT(m_pCur_context_state);
3982 m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
3984 #ifdef VOGL_BUILD_DEBUG
3985 VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
3988 // Add call to current display list
3989 if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
3991 if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
3993 if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
3994 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not listable.\n", VOGL_FUNCTION_NAME);
3996 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
4000 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))
4002 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4007 switch (entrypoint_id)
4009 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4010 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4011 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4012 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4013 case VOGL_ENTRYPOINT_##name: \
4014 { if (!GL_ENTRYPOINT(name)) { process_entrypoint_error("vogl_gl_replayer::process_gl_entrypoint_packet_internal: Can't call NULL GL entrypoint %s (maybe a missing extension?)\n", #name); } else \
4015 GL_ENTRYPOINT(name)(
4016 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4017 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4018 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4019 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4022 #include "gl_glx_simple_replay_funcs.inc"
4023 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4024 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4025 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4026 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4027 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4029 case VOGL_ENTRYPOINT_glXUseXFont:
4031 const key_value_map &key_value_map = trace_packet.get_key_value_map();
4033 const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4034 if ((!pFont_name) || (pFont_name->is_empty()))
4036 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4040 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4043 process_entrypoint_warning("%s: Couldn't load X font %s - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4047 GLint first = trace_packet.get_param_value<int>(1);
4048 GLint count = trace_packet.get_param_value<int>(2);
4049 int trace_list_base = trace_packet.get_param_value<int>(3);
4050 GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4052 GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4054 XFreeFont(m_pWindow->get_display(), pFont);
4056 if (get_context_state()->is_composing_display_list())
4058 process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4062 if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4064 process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4072 case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4074 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4076 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4078 if ((status = post_draw_call()) != cStatusOK)
4083 case VOGL_ENTRYPOINT_glBlitFramebuffer:
4085 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4087 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4089 if ((status = post_draw_call()) != cStatusOK)
4094 case VOGL_ENTRYPOINT_glBegin:
4096 if (m_pCur_context_state->m_inside_gl_begin)
4098 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4100 m_pCur_context_state->m_inside_gl_begin = true;
4102 g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4106 case VOGL_ENTRYPOINT_glEnd:
4108 if (!m_pCur_context_state->m_inside_gl_begin)
4110 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4112 m_pCur_context_state->m_inside_gl_begin = false;
4114 g_vogl_actual_gl_entrypoints.m_glEnd();
4116 if ((status = post_draw_call()) != cStatusOK)
4121 case VOGL_ENTRYPOINT_glGetError:
4123 // TODO: Compare trace error vs. replay error
4127 case VOGL_ENTRYPOINT_glGetStringi:
4129 if (!benchmark_mode())
4131 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4132 trace_packet.get_param_value<GLenum>(0),
4133 trace_packet.get_param_value<GLuint>(1));
4134 VOGL_NOTE_UNUSED(pStr);
4136 // TODO: Compare vs. trace's?
4141 case VOGL_ENTRYPOINT_glGetString:
4143 if (!benchmark_mode())
4145 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4146 trace_packet.get_param_value<GLenum>(0));
4147 VOGL_NOTE_UNUSED(pStr);
4149 // TODO: Compare vs. trace's?
4154 case VOGL_ENTRYPOINT_glGenFramebuffers:
4155 case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4157 if (!gen_handles(get_context_state()->m_framebuffers,
4158 trace_packet.get_param_value<GLsizei>(0),
4159 static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4160 (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4161 return cStatusHardFailure;
4165 case VOGL_ENTRYPOINT_glBindFramebuffer:
4166 case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4168 GLenum target = trace_packet.get_param_value<GLenum>(0);
4169 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4171 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4173 SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4177 case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4178 case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4180 if (!benchmark_mode())
4182 GLenum target = trace_packet.get_param_value<GLenum>(0);
4183 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4184 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4185 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4186 uint trace_params_count = trace_params_size / sizeof(GLint);
4188 int n = g_gl_enums.get_pname_count(pname);
4191 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4192 return cStatusSoftFailure;
4194 else if (n < static_cast<int>(trace_params_count))
4196 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);
4197 return cStatusSoftFailure;
4201 vogl::growable_array<GLint, 16> params(n + 1);
4202 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4204 SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4206 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4208 if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4210 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));
4217 case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4218 case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4221 SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4223 GLenum trace_status = trace_packet.get_return_value<GLenum>();
4224 if (result != trace_status)
4226 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4230 case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4232 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));
4235 case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4237 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));
4240 case VOGL_ENTRYPOINT_glFramebufferTexture:
4242 GLenum target = trace_packet.get_param_value<GLenum>(0);
4243 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4244 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4245 GLuint replay_texture = trace_texture;
4246 GLint level = trace_packet.get_param_value<GLint>(3);
4248 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4251 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);
4254 GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4258 case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4259 case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4261 GLenum target = trace_packet.get_param_value<GLenum>(0);
4262 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4263 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4264 GLuint replay_texture = trace_texture;
4265 GLint level = trace_packet.get_param_value<GLint>(3);
4266 GLint layer = trace_packet.get_param_value<GLint>(4);
4268 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4271 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);
4274 SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4278 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4279 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4280 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4281 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4282 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4283 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4285 GLenum target = trace_packet.get_param_value<GLenum>(0);
4286 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4287 GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4288 GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4289 GLuint replay_texture = trace_texture;
4290 GLint level = trace_packet.get_param_value<GLint>(4);
4292 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4295 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);
4298 switch (entrypoint_id)
4300 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4301 GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4303 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4304 GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4306 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4307 GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4309 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4310 GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4312 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4313 GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4315 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4316 GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4324 case VOGL_ENTRYPOINT_glGenTextures:
4326 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))
4327 return cStatusHardFailure;
4330 case VOGL_ENTRYPOINT_glGenTexturesEXT:
4332 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))
4333 return cStatusHardFailure;
4336 case VOGL_ENTRYPOINT_glDeleteTextures:
4338 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));
4341 case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4343 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));
4346 case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4348 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4350 GLuint trace_texture = texture;
4351 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4353 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4356 VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4358 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4360 if (!check_gl_error())
4361 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4366 case VOGL_ENTRYPOINT_glBindTexture:
4367 case VOGL_ENTRYPOINT_glBindTextureEXT:
4369 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4371 GLuint trace_texture = texture;
4372 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4374 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4377 SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4379 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4381 if (!check_gl_error())
4382 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4387 case VOGL_ENTRYPOINT_glBindSampler:
4389 GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4390 GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4393 case VOGL_ENTRYPOINT_glDeleteSamplers:
4395 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));
4398 case VOGL_ENTRYPOINT_glGenSamplers:
4400 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))
4401 return cStatusHardFailure;
4405 case VOGL_ENTRYPOINT_glSamplerParameterf:
4407 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4408 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4409 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4412 case VOGL_ENTRYPOINT_glSamplerParameteri:
4414 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4415 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4416 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4419 case VOGL_ENTRYPOINT_glSamplerParameterfv:
4421 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4422 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4423 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4426 case VOGL_ENTRYPOINT_glSamplerParameteriv:
4428 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4429 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4430 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4433 case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4435 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4436 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4437 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4440 case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4442 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4443 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4444 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4447 case VOGL_ENTRYPOINT_glGenBuffers:
4448 case VOGL_ENTRYPOINT_glGenBuffersARB:
4450 uint n = trace_packet.get_param_value<GLsizei>(0);
4451 const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4453 if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4455 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4456 return cStatusHardFailure;
4460 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4461 return cStatusHardFailure;
4466 for (uint i = 0; i < n; i++)
4468 if (pTrace_handles[i])
4469 get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4475 case VOGL_ENTRYPOINT_glDeleteBuffers:
4476 case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4478 GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4479 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4480 uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4482 if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4484 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4485 return cStatusHardFailure;
4488 for (GLsizei iter = 0; iter < trace_n; iter++)
4490 GLuint trace_id = pTrace_ids[iter];
4494 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4496 process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4499 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4500 if (it == get_shared_state()->m_buffers.end())
4502 process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4506 GLuint replay_id = it->second;
4508 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4510 for (uint i = 0; i < mapped_bufs.size(); i++)
4512 if (mapped_bufs[i].m_buffer == replay_id)
4514 process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4516 mapped_bufs.erase_unordered(i);
4522 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4523 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4525 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4529 case VOGL_ENTRYPOINT_glGenProgramsARB:
4531 // arb program objects
4532 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4534 if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4535 return cStatusHardFailure;
4537 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4538 if (pTrace_programs[i])
4539 get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4543 case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4545 // arb program objects
4546 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4548 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4549 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4551 delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4554 case VOGL_ENTRYPOINT_glBindProgramARB:
4556 // arb program objects
4557 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4559 GLuint trace_program = program;
4560 gl_handle_hash_map::const_iterator it;
4563 it = get_shared_state()->m_arb_programs.find(program);
4564 if (it != get_shared_state()->m_arb_programs.end())
4565 program = it->second;
4567 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);
4572 VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4574 if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4578 if (it == get_shared_state()->m_arb_programs.end())
4579 get_shared_state()->m_arb_programs.insert(trace_program, program);
4581 get_shared_state()->m_arb_program_targets[trace_program] = target;
4586 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));
4587 return cStatusGLError;
4592 case VOGL_ENTRYPOINT_glIsProgramARB:
4594 if (!benchmark_mode())
4596 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4598 GLuint trace_program = program;
4599 program = map_handle(get_shared_state()->m_arb_programs, program);
4601 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4602 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4604 if (trace_result != replay_result)
4605 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);
4610 case VOGL_ENTRYPOINT_glGenQueries:
4611 case VOGL_ENTRYPOINT_glGenQueriesARB:
4613 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4614 vogl::growable_array<GLuint, 16> replay_handles(n);
4616 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()))
4617 return cStatusHardFailure;
4619 for (GLsizei i = 0; i < n; i++)
4620 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4624 case VOGL_ENTRYPOINT_glDeleteQueries:
4625 case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4627 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4628 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4632 for (GLsizei i = 0; i < n; i++)
4634 GLuint trace_id = pTrace_ids[i];
4637 gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4638 if (it != get_shared_state()->m_queries.end())
4639 get_shared_state()->m_query_targets.erase(it->second);
4643 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4644 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));
4646 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));
4650 case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4652 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))
4653 return cStatusHardFailure;
4656 case VOGL_ENTRYPOINT_glGenRenderbuffers:
4658 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))
4659 return cStatusHardFailure;
4662 case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4664 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));
4667 case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4669 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));
4672 case VOGL_ENTRYPOINT_glIsRenderbuffer:
4674 if (!benchmark_mode())
4676 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4677 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4678 if (replay_result != trace_result)
4680 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);
4685 case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4687 if (!benchmark_mode())
4689 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4690 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4691 if (replay_result != trace_result)
4693 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);
4698 case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4700 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)));
4703 case VOGL_ENTRYPOINT_glBindRenderbuffer:
4705 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)));
4708 case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4710 GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4711 trace_packet.get_param_value<GLenum>(0),
4712 trace_packet.get_param_value<GLenum>(1),
4713 trace_packet.get_param_value<GLenum>(2),
4714 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4717 case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4719 GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4720 trace_packet.get_param_value<GLenum>(0),
4721 trace_packet.get_param_value<GLenum>(1),
4722 trace_packet.get_param_value<GLenum>(2),
4723 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4726 case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4727 case VOGL_ENTRYPOINT_glUseProgram:
4729 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4730 handle_use_program(trace_handle, entrypoint_id);
4733 case VOGL_ENTRYPOINT_glProgramParameteri:
4734 case VOGL_ENTRYPOINT_glProgramParameteriARB:
4735 case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4737 VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4739 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4741 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4742 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4743 else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4744 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4746 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4750 case VOGL_ENTRYPOINT_glBindFragDataLocation:
4751 case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4753 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4755 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4757 if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4758 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4760 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4764 case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4766 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4768 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4770 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4774 case VOGL_ENTRYPOINT_glValidateProgramARB:
4776 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4778 programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4780 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4784 case VOGL_ENTRYPOINT_glValidateProgram:
4786 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4788 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4790 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4794 case VOGL_ENTRYPOINT_glCreateProgram:
4795 case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4797 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4800 GLuint replay_handle;
4802 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4803 replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4805 replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4807 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4809 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4810 return cStatusHardFailure;
4814 case VOGL_ENTRYPOINT_glDeleteProgram:
4816 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4817 handle_delete_program(trace_handle);
4821 case VOGL_ENTRYPOINT_glDeleteObjectARB:
4823 GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4824 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4826 if (target == VOGL_SHADER_OBJECT)
4827 handle_delete_shader(trace_handle);
4828 else if (target == VOGL_PROGRAM_OBJECT)
4829 handle_delete_program(trace_handle);
4832 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4834 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);
4835 return cStatusSoftFailure;
4840 case VOGL_ENTRYPOINT_glDeleteShader:
4842 GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4843 handle_delete_shader(trace_shader);
4847 case VOGL_ENTRYPOINT_glCreateShader:
4848 case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4850 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4853 GLuint replay_handle;
4855 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4856 replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4858 replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4860 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4862 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4863 return cStatusHardFailure;
4867 case VOGL_ENTRYPOINT_glAttachShader:
4869 GL_ENTRYPOINT(glAttachShader)(
4870 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4871 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4874 case VOGL_ENTRYPOINT_glAttachObjectARB:
4876 GL_ENTRYPOINT(glAttachObjectARB)(
4877 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4878 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4881 case VOGL_ENTRYPOINT_glDetachShader:
4883 handle_detach_shader(entrypoint_id);
4887 case VOGL_ENTRYPOINT_glDetachObjectARB:
4889 GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4891 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4893 if (target == VOGL_SHADER_OBJECT)
4894 handle_detach_shader(entrypoint_id);
4897 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4898 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4903 case VOGL_ENTRYPOINT_glBindAttribLocation:
4905 GL_ENTRYPOINT(glBindAttribLocation)(
4906 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4907 trace_packet.get_param_value<GLuint>(1),
4908 trace_packet.get_param_client_memory<GLchar>(2));
4911 case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4913 GL_ENTRYPOINT(glBindAttribLocationARB)(
4914 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4915 trace_packet.get_param_value<GLuint>(1),
4916 trace_packet.get_param_client_memory<GLcharARB>(2));
4919 case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4921 if (!benchmark_mode())
4923 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4924 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4926 int n = g_gl_enums.get_pname_count(pname);
4929 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4930 return cStatusSoftFailure;
4934 vogl::growable_array<GLint, 16> params(n + 1);
4935 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4937 GL_ENTRYPOINT(glGetObjectParameterivARB)(
4938 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4942 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4944 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4946 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));
4952 case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4954 if (!benchmark_mode())
4956 GLenum target = trace_packet.get_param_value<GLenum>(0);
4957 GLenum value = trace_packet.get_param_value<GLenum>(1);
4958 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4960 int n = g_gl_enums.get_pname_count(value);
4963 process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4964 return cStatusSoftFailure;
4968 vogl::growable_array<GLint, 16> data(n + 1);
4969 data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4971 GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4973 VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4975 GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
4976 if (data[0] != trace_data)
4978 process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
4979 vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
4987 case VOGL_ENTRYPOINT_glGetBufferPointerv:
4989 if (!benchmark_mode())
4991 GLvoid *pReplay_ptr = NULL;
4992 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
4994 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
4995 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;
4997 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
4999 process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
5000 vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
5006 case VOGL_ENTRYPOINT_glShaderSource:
5007 case VOGL_ENTRYPOINT_glShaderSourceARB:
5009 const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5010 trace_packet.get_param_value<GLsizei>(1),
5011 trace_packet.get_param_client_memory_array(2),
5012 trace_packet.get_param_client_memory<const GLint>(3));
5013 if (status != cStatusOK)
5017 case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5019 GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5020 GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5023 GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5026 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5027 return cStatusSoftFailure;
5031 vogl::vector<GLchar> log(length);
5033 GLsizei actual_length = 0;
5034 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5038 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());
5044 case VOGL_ENTRYPOINT_glGetPointerv:
5046 if (!benchmark_mode())
5049 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5051 // TODO: Differ vs. trace's in some way?
5056 case VOGL_ENTRYPOINT_glGetInfoLogARB:
5058 GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5059 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5061 GLsizei length = -1;
5062 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5065 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5066 return cStatusSoftFailure;
5070 vogl::vector<GLcharARB> log(length);
5072 GLsizei actual_length = 0;
5073 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5077 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());
5083 case VOGL_ENTRYPOINT_glGetUniformLocation:
5085 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5086 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5087 GLint trace_loc = trace_packet.get_return_value<GLint>();
5091 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5093 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5097 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);
5102 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);
5105 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5106 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5107 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5109 glsl_program_state &state = it->second;
5110 state.m_uniform_locations.erase(trace_loc);
5111 state.m_uniform_locations.insert(trace_loc, replay_loc);
5118 case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5120 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5121 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5122 GLint trace_loc = trace_packet.get_return_value<GLint>();
5126 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5128 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5132 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);
5137 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);
5140 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5141 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5142 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5144 glsl_program_state &state = it->second;
5145 state.m_uniform_locations.erase(trace_loc);
5146 state.m_uniform_locations.insert(trace_loc, replay_loc);
5153 case VOGL_ENTRYPOINT_glGetActiveAttrib:
5154 case VOGL_ENTRYPOINT_glGetActiveUniform:
5156 if (!benchmark_mode())
5158 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5159 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5161 GLuint index = trace_packet.get_param_value<GLuint>(1);
5162 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5164 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5165 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5166 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5167 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5169 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5175 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5176 GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5178 GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5180 bool mismatch = false;
5182 GLsizei trace_len = 0;
5185 trace_len = pTrace_length[0];
5186 if (trace_len != len)
5190 GLint trace_size = 0;
5193 trace_size = pTrace_size[0];
5194 if (trace_size != size)
5198 GLenum trace_type = 0;
5201 trace_type = pTrace_type[0];
5202 if (trace_type != type)
5206 if ((bufSize) && (pTrace_name))
5208 uint n = vogl_strlen((const char *)pTrace_name) + 1;
5209 if (bufSize < (GLsizei)n)
5211 else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5217 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5218 vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5219 (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5220 vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5221 (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5227 case VOGL_ENTRYPOINT_glGetAttachedShaders:
5229 if (!benchmark_mode())
5231 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5232 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5234 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5236 vogl::growable_array<GLuint, 16> shaders(max_count);
5238 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5240 // TODO: Diff results
5245 case VOGL_ENTRYPOINT_glGetAttribLocation:
5247 if (!benchmark_mode())
5249 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5250 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5252 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5254 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5255 GLint trace_result = trace_packet.get_return_value<GLint>();
5257 if (replay_result != trace_result)
5259 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5260 vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5266 case VOGL_ENTRYPOINT_glGetProgramivARB:
5268 if (!benchmark_mode())
5270 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5271 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5272 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5273 uint params_count = params_size / sizeof(GLint);
5275 int n = g_gl_enums.get_pname_count(pname);
5278 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5279 return cStatusSoftFailure;
5283 vogl::growable_array<GLint, 16> params(n + 1);
5284 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5286 GL_ENTRYPOINT(glGetProgramivARB)(
5287 trace_packet.get_param_value<GLenum>(0),
5291 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5293 if (params_count != static_cast<uint>(n))
5295 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5297 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5299 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));
5306 case VOGL_ENTRYPOINT_glGetProgramiv:
5308 if (!benchmark_mode())
5310 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5311 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5313 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5315 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5316 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5317 uint params_count = params_size / sizeof(GLint);
5319 int n = g_gl_enums.get_pname_count(pname);
5322 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5323 return cStatusSoftFailure;
5327 vogl::growable_array<GLint, 16> params(n + 1);
5328 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5330 GL_ENTRYPOINT(glGetProgramiv)(
5335 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5337 if (params_count != static_cast<uint>(n))
5339 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5341 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5343 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));
5350 case VOGL_ENTRYPOINT_glLinkProgram:
5351 case VOGL_ENTRYPOINT_glLinkProgramARB:
5352 case VOGL_ENTRYPOINT_glProgramBinary:
5354 handle_link_program(entrypoint_id);
5358 case VOGL_ENTRYPOINT_glCompileShader:
5360 GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5363 case VOGL_ENTRYPOINT_glCompileShaderARB:
5365 GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5368 case VOGL_ENTRYPOINT_glGetShaderiv:
5370 if (!benchmark_mode())
5372 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5373 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5375 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5378 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5380 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, ¶ms);
5382 if ((pClient_params) && (*pClient_params != params))
5384 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5385 vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5391 case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5393 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5394 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5396 GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5397 const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5398 VOGL_NOTE_UNUSED(pTrace_length);
5399 const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5400 VOGL_NOTE_UNUSED(pTrace_info_log);
5402 vogl::growable_array<GLchar, 512> log(trace_max_length);
5404 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5408 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());
5413 case VOGL_ENTRYPOINT_glGetBooleanv:
5415 if (!benchmark_mode())
5417 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5418 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5420 int n = g_gl_enums.get_pname_count(pname);
5423 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));
5424 return cStatusSoftFailure;
5428 vogl::growable_array<GLboolean, 16> params(n + 1);
5429 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5431 GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5433 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5435 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5437 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));
5444 case VOGL_ENTRYPOINT_glGetDoublev:
5446 if (!benchmark_mode())
5448 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5449 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5451 int n = g_gl_enums.get_pname_count(pname);
5454 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5455 return cStatusSoftFailure;
5459 vogl::growable_array<GLdouble, 17> params(n + 1);
5460 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5462 GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5464 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5466 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5468 process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5475 case VOGL_ENTRYPOINT_glGetFloatv:
5477 if (!benchmark_mode())
5479 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5480 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5481 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5483 int n = g_gl_enums.get_pname_count(pname);
5486 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5487 return cStatusSoftFailure;
5490 vogl::growable_array<GLfloat, 17> params(n + 1);
5491 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5493 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5495 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5497 if (static_cast<int>(trace_params_count) < n)
5498 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5499 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5501 process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5507 case VOGL_ENTRYPOINT_glGetIntegerv:
5509 if (!benchmark_mode())
5511 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5512 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5513 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5515 int n = g_gl_enums.get_pname_count(pname);
5518 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5519 return cStatusSoftFailure;
5522 vogl::growable_array<GLint, 16> params(n + 1);
5523 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5525 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5527 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5529 bool is_binding = false;
5532 case GL_ARRAY_BUFFER_BINDING:
5533 case GL_COLOR_ARRAY_BUFFER_BINDING:
5534 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5535 case GL_DRAW_FRAMEBUFFER_BINDING:
5536 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5537 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5538 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5539 case GL_INDEX_ARRAY_BUFFER_BINDING:
5540 case GL_NORMAL_ARRAY_BUFFER_BINDING:
5541 case GL_PIXEL_PACK_BUFFER_BINDING:
5542 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5543 case GL_PROGRAM_PIPELINE_BINDING:
5544 case GL_READ_FRAMEBUFFER_BINDING:
5545 case GL_RENDERBUFFER_BINDING:
5546 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5547 case GL_SHADER_STORAGE_BUFFER_BINDING:
5548 case GL_TEXTURE_BINDING_1D:
5549 case GL_TEXTURE_BINDING_1D_ARRAY:
5550 case GL_TEXTURE_BINDING_2D:
5551 case GL_TEXTURE_BINDING_2D_ARRAY:
5552 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5553 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5554 case GL_TEXTURE_BINDING_3D:
5555 case GL_TEXTURE_BINDING_BUFFER:
5556 case GL_TEXTURE_BINDING_CUBE_MAP:
5557 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5558 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5559 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5560 case GL_UNIFORM_BUFFER_BINDING:
5561 case GL_VERTEX_ARRAY_BINDING:
5562 case GL_VERTEX_ARRAY_BUFFER_BINDING:
5563 case GL_CURRENT_PROGRAM:
5572 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5575 if (static_cast<int>(trace_params_count) < n)
5577 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5579 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5581 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));
5582 for (int i = 0; i < n; i++)
5583 vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5590 // glProgramUniform's
5591 case VOGL_ENTRYPOINT_glProgramUniform1f:
5593 set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5596 case VOGL_ENTRYPOINT_glProgramUniform1i:
5598 set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5601 case VOGL_ENTRYPOINT_glProgramUniform1ui:
5603 set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5606 case VOGL_ENTRYPOINT_glProgramUniform2f:
5608 set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5611 case VOGL_ENTRYPOINT_glProgramUniform2i:
5613 set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5616 case VOGL_ENTRYPOINT_glProgramUniform2ui:
5618 set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5621 case VOGL_ENTRYPOINT_glProgramUniform3f:
5623 set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5626 case VOGL_ENTRYPOINT_glProgramUniform3i:
5628 set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5631 case VOGL_ENTRYPOINT_glProgramUniform3ui:
5633 set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5636 case VOGL_ENTRYPOINT_glProgramUniform4f:
5638 set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5641 case VOGL_ENTRYPOINT_glProgramUniform4i:
5643 set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5646 case VOGL_ENTRYPOINT_glProgramUniform4ui:
5648 set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5651 case VOGL_ENTRYPOINT_glProgramUniform1fv:
5653 set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5656 case VOGL_ENTRYPOINT_glProgramUniform2fv:
5658 set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5661 case VOGL_ENTRYPOINT_glProgramUniform3fv:
5663 set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5666 case VOGL_ENTRYPOINT_glProgramUniform4fv:
5668 set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5671 case VOGL_ENTRYPOINT_glProgramUniform1iv:
5673 set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5676 case VOGL_ENTRYPOINT_glProgramUniform2iv:
5678 set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5681 case VOGL_ENTRYPOINT_glProgramUniform3iv:
5683 set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5686 case VOGL_ENTRYPOINT_glProgramUniform4iv:
5688 set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5691 case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5693 set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5696 case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5698 set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5701 case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5703 set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5706 case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5708 set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5711 case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5713 set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5716 case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5718 set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5721 case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5723 set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5726 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5728 set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5731 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5733 set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5736 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5738 set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5741 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5743 set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5746 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5748 set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5751 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5753 set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5757 case VOGL_ENTRYPOINT_glUniform1f:
5759 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5762 case VOGL_ENTRYPOINT_glUniform1fARB:
5764 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5767 case VOGL_ENTRYPOINT_glUniform2f:
5769 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5772 case VOGL_ENTRYPOINT_glUniform2fARB:
5774 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5777 case VOGL_ENTRYPOINT_glUniform3f:
5779 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5782 case VOGL_ENTRYPOINT_glUniform3fARB:
5784 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5787 case VOGL_ENTRYPOINT_glUniform4f:
5789 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5792 case VOGL_ENTRYPOINT_glUniform4fARB:
5794 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5797 case VOGL_ENTRYPOINT_glUniform1i:
5799 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5802 case VOGL_ENTRYPOINT_glUniform1iARB:
5804 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5807 case VOGL_ENTRYPOINT_glUniform2i:
5809 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5812 case VOGL_ENTRYPOINT_glUniform2iARB:
5814 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5817 case VOGL_ENTRYPOINT_glUniform3i:
5819 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5822 case VOGL_ENTRYPOINT_glUniform3iARB:
5824 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5827 case VOGL_ENTRYPOINT_glUniform4i:
5829 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5832 case VOGL_ENTRYPOINT_glUniform4iARB:
5834 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5837 case VOGL_ENTRYPOINT_glUniform1ui:
5839 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5842 case VOGL_ENTRYPOINT_glUniform1uiEXT:
5844 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5847 case VOGL_ENTRYPOINT_glUniform2ui:
5849 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5852 case VOGL_ENTRYPOINT_glUniform2uiEXT:
5854 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5857 case VOGL_ENTRYPOINT_glUniform3ui:
5859 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5862 case VOGL_ENTRYPOINT_glUniform3uiEXT:
5864 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5867 case VOGL_ENTRYPOINT_glUniform4ui:
5869 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5872 case VOGL_ENTRYPOINT_glUniform4uiEXT:
5874 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5877 case VOGL_ENTRYPOINT_glUniform1uiv:
5879 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5882 case VOGL_ENTRYPOINT_glUniform1uivEXT:
5884 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5887 case VOGL_ENTRYPOINT_glUniform2uiv:
5889 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5892 case VOGL_ENTRYPOINT_glUniform2uivEXT:
5894 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5897 case VOGL_ENTRYPOINT_glUniform3uiv:
5899 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5902 case VOGL_ENTRYPOINT_glUniform3uivEXT:
5904 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5907 case VOGL_ENTRYPOINT_glUniform4uiv:
5909 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5912 case VOGL_ENTRYPOINT_glUniform4uivEXT:
5914 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5917 case VOGL_ENTRYPOINT_glUniform1iv:
5919 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5922 case VOGL_ENTRYPOINT_glUniform1ivARB:
5924 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5927 case VOGL_ENTRYPOINT_glUniform2iv:
5929 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5932 case VOGL_ENTRYPOINT_glUniform2ivARB:
5934 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5937 case VOGL_ENTRYPOINT_glUniform3iv:
5939 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5942 case VOGL_ENTRYPOINT_glUniform3ivARB:
5944 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5947 case VOGL_ENTRYPOINT_glUniform4iv:
5949 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5952 case VOGL_ENTRYPOINT_glUniform4ivARB:
5954 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5957 case VOGL_ENTRYPOINT_glUniform1fv:
5959 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5962 case VOGL_ENTRYPOINT_glUniform1fvARB:
5964 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5967 case VOGL_ENTRYPOINT_glUniform2fv:
5969 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5972 case VOGL_ENTRYPOINT_glUniform2fvARB:
5974 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
5977 case VOGL_ENTRYPOINT_glUniform3fv:
5979 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
5982 case VOGL_ENTRYPOINT_glUniform3fvARB:
5984 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
5987 case VOGL_ENTRYPOINT_glUniform4fv:
5989 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
5992 case VOGL_ENTRYPOINT_glUniform4fvARB:
5994 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
5997 case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
5999 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
6002 case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6004 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6007 case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6009 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6012 case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6014 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6017 case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6019 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6022 case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6024 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6027 case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6029 set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6032 case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6034 set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6037 case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6039 set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6042 case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6044 set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6047 case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6049 set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6052 case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6054 set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6057 case VOGL_ENTRYPOINT_glBeginQuery:
6058 case VOGL_ENTRYPOINT_glBeginQueryARB:
6060 GLenum target = trace_packet.get_param_value<GLenum>(0);
6061 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6062 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6064 if (!m_pCur_context_state->m_inside_gl_begin)
6067 if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6068 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6070 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6072 if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6074 if (check_gl_error())
6075 return cStatusGLError;
6077 get_shared_state()->m_query_targets[replay_handle] = target;
6082 case VOGL_ENTRYPOINT_glEndQuery:
6084 GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6087 case VOGL_ENTRYPOINT_glEndQueryARB:
6089 GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6092 case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6094 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6095 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6097 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6099 int n = g_gl_enums.get_pname_count(pname);
6102 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6103 return cStatusSoftFailure;
6107 vogl::growable_array<GLint, 16> params(n + 1);
6108 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6110 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6112 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6117 case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6119 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6120 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6122 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6124 int n = g_gl_enums.get_pname_count(pname);
6127 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6128 return cStatusSoftFailure;
6132 vogl::growable_array<GLint, 16> params(n + 1);
6133 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6135 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6137 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6142 case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6144 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6145 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6147 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6149 int n = g_gl_enums.get_pname_count(pname);
6152 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6153 return cStatusSoftFailure;
6157 vogl::growable_array<GLuint, 16> params(n + 1);
6158 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6160 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6162 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6167 case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6169 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6170 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6172 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6174 int n = g_gl_enums.get_pname_count(pname);
6177 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6178 return cStatusSoftFailure;
6182 vogl::growable_array<GLuint, 16> params(n + 1);
6183 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6185 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6187 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6192 case VOGL_ENTRYPOINT_glQueryCounter:
6194 VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6196 id = map_handle(get_shared_state()->m_queries, id);
6198 VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6202 case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6204 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6205 VOGL_NOTE_UNUSED(pTrace_params);
6207 id = map_handle(get_shared_state()->m_queries, id);
6209 int n = g_gl_enums.get_pname_count(pname);
6212 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6213 return cStatusSoftFailure;
6216 vogl::growable_array<GLint64, 16> temp_params(n + 1);
6217 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6219 GLint64 *pReplay_params = temp_params.get_ptr();
6221 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6223 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6227 case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6229 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6230 VOGL_NOTE_UNUSED(pTrace_params);
6232 id = map_handle(get_shared_state()->m_queries, id);
6234 int n = g_gl_enums.get_pname_count(pname);
6237 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6238 return cStatusSoftFailure;
6241 vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6242 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6244 GLuint64 *pReplay_params = temp_params.get_ptr();
6246 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6248 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6252 case VOGL_ENTRYPOINT_glBindBuffer:
6253 case VOGL_ENTRYPOINT_glBindBufferARB:
6255 GLenum target = trace_packet.get_param_value<GLenum>(0);
6256 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6257 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6261 SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6263 if (check_gl_error())
6264 return cStatusGLError;
6266 if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6268 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6270 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6271 else if (*pBinding == GL_NONE)
6277 case VOGL_ENTRYPOINT_glBindBufferBase:
6278 case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6279 case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6281 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6283 GLuint trace_buffer = buffer;
6284 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6288 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6289 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6290 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6291 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6293 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6295 if (check_gl_error())
6296 return cStatusGLError;
6298 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6300 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6302 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6303 else if (*pBinding == GL_NONE)
6309 case VOGL_ENTRYPOINT_glBindBufferRange:
6310 case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6311 case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6313 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6315 GLuint trace_buffer = buffer;
6316 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6320 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6321 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6322 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6323 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6325 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6327 if (check_gl_error())
6328 return cStatusGLError;
6330 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6332 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6334 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6335 else if (*pBinding == GL_NONE)
6341 case VOGL_ENTRYPOINT_glFenceSync:
6343 vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6346 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6349 process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6350 return cStatusHardFailure;
6354 get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6360 case VOGL_ENTRYPOINT_glWaitSync:
6361 case VOGL_ENTRYPOINT_glClientWaitSync:
6363 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6364 GLsync replay_sync = NULL;
6366 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6367 if (it == get_shared_state()->m_syncs.end())
6371 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6372 return cStatusHardFailure;
6377 replay_sync = it->second;
6380 if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6381 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6383 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6387 case VOGL_ENTRYPOINT_glDeleteSync:
6389 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6390 GLsync replay_sync = NULL;
6392 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6393 if (it == get_shared_state()->m_syncs.end())
6397 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6398 return cStatusHardFailure;
6403 replay_sync = it->second;
6406 GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6410 get_shared_state()->m_syncs.erase(trace_sync);
6415 case VOGL_ENTRYPOINT_glVertexPointer:
6417 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),
6418 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6421 case VOGL_ENTRYPOINT_glVertexPointerEXT:
6423 VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6424 VOGL_NOTE_UNUSED(pTrace_pointer);
6426 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]);
6429 case VOGL_ENTRYPOINT_glColorPointer:
6431 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),
6432 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6435 case VOGL_ENTRYPOINT_glColorPointerEXT:
6437 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6438 VOGL_NOTE_UNUSED(pTrace_pointer);
6440 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]);
6443 case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6445 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),
6446 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6449 case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6451 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),
6452 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6455 case VOGL_ENTRYPOINT_glTexCoordPointer:
6457 GLint cur_client_active_texture = 0;
6458 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6460 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6461 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6463 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);
6464 return cStatusSoftFailure;
6467 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),
6468 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6471 case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6473 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6474 VOGL_NOTE_UNUSED(pTrace_pointer);
6476 GLint cur_client_active_texture = 0;
6477 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6479 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6480 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6482 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);
6483 return cStatusSoftFailure;
6486 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]);
6489 case VOGL_ENTRYPOINT_glFogCoordPointer:
6491 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),
6492 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6495 case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6497 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),
6498 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6501 case VOGL_ENTRYPOINT_glIndexPointer:
6503 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),
6504 vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6507 case VOGL_ENTRYPOINT_glIndexPointerEXT:
6509 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6510 VOGL_NOTE_UNUSED(pTrace_pointer);
6512 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6515 case VOGL_ENTRYPOINT_glNormalPointer:
6517 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6518 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6521 case VOGL_ENTRYPOINT_glNormalPointerEXT:
6523 VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6524 VOGL_NOTE_UNUSED(pTrace_pointer);
6526 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6529 case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6531 vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6532 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6535 case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6537 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6538 VOGL_NOTE_UNUSED(pTrace_pointer);
6540 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));
6543 case VOGL_ENTRYPOINT_glInterleavedArrays:
6545 // TODO: Test this more!
6546 GLenum format = trace_packet.get_param_value<GLenum>(0);
6547 GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6548 const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6551 for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6552 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6554 if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6556 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6557 return cStatusSoftFailure;
6562 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6563 return cStatusSoftFailure;
6566 const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6571 VOGL_ASSERT(stride > 0);
6574 GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6575 GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6576 GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6577 GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6583 GLint cur_client_active_texture = 0;
6584 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6586 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6587 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6589 process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6590 return cStatusSoftFailure;
6593 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6594 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6595 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6599 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6606 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6607 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6608 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6612 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6619 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6620 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6621 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6625 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6630 GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6631 vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6632 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6636 case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6637 case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6639 GLuint index = trace_packet.get_param_value<GLuint>(0);
6640 GLint size = trace_packet.get_param_value<GLint>(1);
6641 GLenum type = trace_packet.get_param_value<GLenum>(2);
6642 GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6643 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6645 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6647 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6648 return cStatusSoftFailure;
6651 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6652 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6653 if ((!buffer) && (trace_pointer))
6655 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6656 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6657 if (!m_client_side_vertex_attrib_data[index].size())
6659 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6661 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6664 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6665 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6667 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6671 case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6672 case VOGL_ENTRYPOINT_glVertexAttribPointer:
6674 GLuint index = trace_packet.get_param_value<GLuint>(0);
6675 GLint size = trace_packet.get_param_value<GLint>(1);
6676 GLenum type = trace_packet.get_param_value<GLenum>(2);
6677 GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6678 GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6679 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6681 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6683 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6684 return cStatusSoftFailure;
6687 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6688 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6689 if ((!buffer) && (trace_pointer))
6691 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6692 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6693 if (!m_client_side_vertex_attrib_data[index].size())
6695 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6697 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6700 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6701 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6703 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6707 case VOGL_ENTRYPOINT_glDrawRangeElements:
6708 case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6710 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6711 GLuint start = trace_packet.get_param_value<GLuint>(1);
6712 GLuint end = trace_packet.get_param_value<GLuint>(2);
6713 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6714 GLenum type = trace_packet.get_param_value<GLenum>(4);
6715 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6717 const GLvoid *pIndices;
6718 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6719 return cStatusSoftFailure;
6721 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6723 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6724 GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6726 GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6731 case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6733 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6734 GLuint start = trace_packet.get_param_value<GLuint>(1);
6735 GLuint end = trace_packet.get_param_value<GLuint>(2);
6736 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6737 GLenum type = trace_packet.get_param_value<GLenum>(4);
6738 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6739 GLint basevertex = trace_packet.get_param_value<GLint>(6);
6741 const GLvoid *pIndices;
6742 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6743 return cStatusSoftFailure;
6745 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6747 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6752 case VOGL_ENTRYPOINT_glDrawElements:
6754 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6755 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6756 GLenum type = trace_packet.get_param_value<GLenum>(2);
6757 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6759 const GLvoid *pIndices;
6760 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6761 return cStatusSoftFailure;
6763 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6765 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6770 case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6771 case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6773 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6775 const GLvoid *pIndices = NULL;
6776 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6777 return cStatusSoftFailure;
6779 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6781 GLsizei start = first, primcount = instancecount;
6782 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6785 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6789 case VOGL_ENTRYPOINT_glDrawArrays:
6790 case VOGL_ENTRYPOINT_glDrawArraysEXT:
6792 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6793 GLint first = trace_packet.get_param_value<GLint>(1);
6794 GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6796 const GLvoid *pIndices = NULL;
6797 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6798 return cStatusSoftFailure;
6800 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6802 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6803 GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6805 GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6810 case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6811 case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6812 case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6814 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6815 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6816 GLenum type = trace_packet.get_param_value<GLenum>(2);
6817 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6818 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6820 const GLvoid *pIndices;
6821 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6822 return cStatusSoftFailure;
6824 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6826 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6827 GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6828 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6829 GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6831 GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6836 case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6838 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6839 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6840 GLenum type = trace_packet.get_param_value<GLenum>(2);
6841 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6842 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6843 GLint basevertex = trace_packet.get_param_value<GLint>(5);
6845 const GLvoid *pIndices;
6846 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6847 return cStatusSoftFailure;
6849 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6851 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6856 case VOGL_ENTRYPOINT_glMultiDrawArrays:
6857 case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6859 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6861 const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6862 uint first_size = trace_packet.get_param_client_memory_data_size(1);
6864 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6865 uint count_size = trace_packet.get_param_client_memory_data_size(2);
6867 GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6869 if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6871 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6872 return cStatusSoftFailure;
6875 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6877 // Multi-draws with client side arrays are not supported for replay.
6878 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6879 GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6881 GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6886 case VOGL_ENTRYPOINT_glMultiDrawElements:
6887 case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6889 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6891 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6892 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6894 GLenum type = trace_packet.get_param_value<GLenum>(2);
6896 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6898 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6900 if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6902 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6903 return cStatusSoftFailure;
6906 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6907 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6908 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6910 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6912 // Multi-draws with client side arrays are not supported for replay.
6913 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6914 GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6916 GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6921 case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6923 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6925 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6926 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6928 GLenum type = trace_packet.get_param_value<GLenum>(2);
6930 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6931 //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6932 //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6934 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6936 const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6937 uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6939 if ((count_size != primcount * sizeof(GLsizei)) ||
6940 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6941 (base_vertex_size != primcount * sizeof(GLint)))
6943 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);
6944 return cStatusSoftFailure;
6947 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6948 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6949 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6951 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6953 // Multi-draws with client side arrays are not supported for replay.
6954 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6959 case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6961 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6962 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6963 GLenum type = trace_packet.get_param_value<GLenum>(2);
6964 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6965 GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6967 const GLvoid *pIndices;
6968 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6969 return cStatusSoftFailure;
6971 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6973 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
6978 case VOGL_ENTRYPOINT_glGetBufferSubData:
6980 if (!benchmark_mode())
6982 GLenum target = trace_packet.get_param_value<GLenum>(0);
6983 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
6984 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
6985 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
6987 if (offset != static_cast<uintptr_t>(offset))
6989 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
6990 return cStatusHardFailure;
6993 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
6995 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
6996 return cStatusHardFailure;
6999 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
7001 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
7003 if ((buf.size()) && (pTrace_ptr))
7005 if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7007 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7014 case VOGL_ENTRYPOINT_glGetClipPlane:
7016 if (!benchmark_mode())
7018 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7019 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7021 GLdouble equation[4];
7022 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7024 if (pTrace_equation)
7026 if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7028 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7035 case VOGL_ENTRYPOINT_glBufferData:
7036 case VOGL_ENTRYPOINT_glBufferDataARB:
7038 GLenum target = trace_packet.get_param_value<GLenum>(0);
7039 vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7040 const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7041 uint data_size = trace_packet.get_param_client_memory_data_size(2);
7042 GLenum usage = trace_packet.get_param_value<GLenum>(3);
7044 if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7046 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7047 return cStatusHardFailure;
7050 if (size != static_cast<uintptr_t>(size))
7052 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7053 return cStatusHardFailure;
7056 if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7057 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7059 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7061 GLuint buffer = vogl_get_bound_gl_buffer(target);
7064 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7067 for (i = 0; i < mapped_bufs.size(); i++)
7069 if (mapped_bufs[i].m_buffer == buffer)
7071 process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7073 mapped_bufs.erase_unordered(i);
7081 case VOGL_ENTRYPOINT_glMapBufferARB:
7082 case VOGL_ENTRYPOINT_glMapBuffer:
7084 GLenum target = trace_packet.get_param_value<GLenum>(0);
7085 GLenum access = trace_packet.get_param_value<GLenum>(1);
7086 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7088 // FIXME - must call GL even if !pTrace_result
7089 if (trace_result_ptr_value)
7092 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7093 pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7095 pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7099 process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7100 return cStatusHardFailure;
7103 GLuint buffer = vogl_get_bound_gl_buffer(target);
7105 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7108 for (i = 0; i < mapped_bufs.size(); i++)
7110 if (mapped_bufs[i].m_buffer == buffer)
7112 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7113 return cStatusHardFailure;
7117 if (i == mapped_bufs.size())
7120 GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7122 vogl_mapped_buffer_desc m;
7123 m.m_buffer = buffer;
7124 m.m_target = target;
7126 m.m_length = length;
7127 m.m_access = access;
7130 mapped_bufs.push_back(m);
7136 case VOGL_ENTRYPOINT_glMapBufferRange:
7138 GLenum target = trace_packet.get_param_value<GLenum>(0);
7139 vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7140 vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7141 GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7142 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7144 if (offset != static_cast<uintptr_t>(offset))
7146 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7147 return cStatusHardFailure;
7149 if (length != static_cast<uintptr_t>(length))
7151 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7152 return cStatusHardFailure;
7155 // FIXME - must call GL even if !pTrace_result
7156 if (trace_result_ptr_value)
7158 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7161 process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7162 return cStatusHardFailure;
7165 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7167 GLuint buffer = vogl_get_bound_gl_buffer(target);
7169 for (i = 0; i < mapped_bufs.size(); i++)
7171 if (mapped_bufs[i].m_buffer == buffer)
7173 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7174 return cStatusHardFailure;
7178 if (i == mapped_bufs.size())
7180 vogl_mapped_buffer_desc m;
7181 m.m_buffer = buffer;
7182 m.m_target = target;
7183 m.m_offset = offset;
7184 m.m_length = length;
7185 m.m_access = access;
7188 mapped_bufs.push_back(m);
7194 case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7196 // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7199 case VOGL_ENTRYPOINT_glUnmapBufferARB:
7200 case VOGL_ENTRYPOINT_glUnmapBuffer:
7202 GLenum target = trace_packet.get_param_value<GLenum>(0);
7203 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7205 GLuint buffer = vogl_get_bound_gl_buffer(target);
7207 // FIXME - must call GL even if !buffer
7210 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7212 uint mapped_buffers_index;
7213 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7214 if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7216 if (mapped_buffers_index == mapped_bufs.size())
7218 process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7219 return cStatusHardFailure;
7222 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7224 bool writable_map = false;
7225 bool explicit_bit = false;
7226 if (map_desc.m_range)
7228 writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7229 explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7233 writable_map = (map_desc.m_access != GL_READ_ONLY);
7238 const key_value_map &unmap_data = trace_packet.get_key_value_map();
7242 int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7244 for (int i = 0; i < num_flushed_ranges; i++)
7246 int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7247 int64_t size = unmap_data.get_int64(i * 4 + 1);
7248 VOGL_NOTE_UNUSED(size);
7249 const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7252 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7253 return cStatusHardFailure;
7256 if (ofs != static_cast<GLintptr>(ofs))
7258 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7259 return cStatusHardFailure;
7262 VOGL_ASSERT(size == pData->size());
7264 memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7266 GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7271 int64_t ofs = unmap_data.get_int64(0);
7272 VOGL_NOTE_UNUSED(ofs);
7273 int64_t size = unmap_data.get_int64(1);
7274 VOGL_NOTE_UNUSED(size);
7275 const uint8_vec *pData = unmap_data.get_blob(2);
7278 process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7279 return cStatusHardFailure;
7283 memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7288 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7291 GLboolean replay_result;
7292 if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7293 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7295 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7297 if (trace_result != replay_result)
7298 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);
7302 case VOGL_ENTRYPOINT_glGenVertexArrays:
7304 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))
7305 return cStatusHardFailure;
7308 case VOGL_ENTRYPOINT_glBindVertexArray:
7310 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7311 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7313 GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7316 case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7318 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));
7321 case VOGL_ENTRYPOINT_glIsFramebuffer:
7322 case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7324 if (!benchmark_mode())
7326 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7327 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7328 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7330 GLboolean replay_result;
7331 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7332 replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7334 replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7336 if (trace_result != replay_result)
7337 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));
7342 case VOGL_ENTRYPOINT_glIsBuffer:
7344 if (!benchmark_mode())
7346 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7347 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7348 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7350 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7351 if (trace_result != replay_result)
7352 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));
7356 case VOGL_ENTRYPOINT_glIsEnabledi:
7358 if (!benchmark_mode())
7360 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7361 GLuint index = trace_packet.get_param_value<GLuint>(1);
7362 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7364 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7365 if (trace_result != replay_result)
7366 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));
7370 case VOGL_ENTRYPOINT_glIsEnabled:
7372 if (!benchmark_mode())
7374 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7375 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7377 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7378 if (trace_result != replay_result)
7379 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));
7383 case VOGL_ENTRYPOINT_glIsProgram:
7385 if (!benchmark_mode())
7387 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7388 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7389 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7391 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7393 if (trace_result != replay_result)
7394 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));
7398 case VOGL_ENTRYPOINT_glIsQuery:
7400 if (!benchmark_mode())
7402 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7403 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7404 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7406 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7407 if (trace_result != replay_result)
7408 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));
7412 case VOGL_ENTRYPOINT_glIsShader:
7414 if (!benchmark_mode())
7416 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7417 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7418 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7420 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7421 if (trace_result != replay_result)
7422 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));
7426 case VOGL_ENTRYPOINT_glIsTexture:
7427 case VOGL_ENTRYPOINT_glIsTextureEXT:
7429 if (!benchmark_mode())
7431 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7432 GLuint replay_handle = trace_handle;
7433 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7435 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7437 GLboolean replay_result;
7438 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7439 replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7441 replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7443 if (trace_result != replay_result)
7444 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));
7449 case VOGL_ENTRYPOINT_glIsVertexArray:
7451 if (!benchmark_mode())
7453 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7454 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7455 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7457 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7458 if (trace_result != replay_result)
7459 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));
7464 case VOGL_ENTRYPOINT_glReadPixels:
7466 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7468 if (!benchmark_mode())
7470 GLint x = trace_packet.get_param_value<GLint>(0);
7471 GLint y = trace_packet.get_param_value<GLint>(1);
7472 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7473 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7474 GLenum format = trace_packet.get_param_value<GLenum>(4);
7475 GLenum type = trace_packet.get_param_value<GLenum>(5);
7476 const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7477 uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7479 size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7480 if (replay_data_size != trace_data_size)
7482 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7484 else if (!trace_data)
7486 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7489 if (replay_data_size > cUINT32_MAX)
7491 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7492 return cStatusHardFailure;
7495 vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7496 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7498 if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7500 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7502 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7509 case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7511 if (!benchmark_mode())
7513 GLenum target = trace_packet.get_param_value<GLenum>(0);
7514 GLint level = trace_packet.get_param_value<GLint>(1);
7515 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7516 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7517 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7519 int n = g_gl_enums.get_pname_count(pname);
7522 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7523 return cStatusSoftFailure;
7526 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7527 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7529 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7531 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7534 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7535 else if (trace_params_size != sizeof(GLfloat) * n)
7536 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7537 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7538 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7543 case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7545 if (!benchmark_mode())
7547 GLenum target = trace_packet.get_param_value<GLenum>(0);
7548 GLint level = trace_packet.get_param_value<GLint>(1);
7549 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7550 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7551 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7553 int n = g_gl_enums.get_pname_count(pname);
7556 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7557 return cStatusSoftFailure;
7560 vogl::growable_array<GLint, 16> replay_params(n + 1);
7561 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7563 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7565 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7568 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7569 else if (trace_params_size != sizeof(GLint) * n)
7570 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7571 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7572 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7577 case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7578 case VOGL_ENTRYPOINT_glGetTexParameteriv:
7580 if (!benchmark_mode())
7582 GLenum target = trace_packet.get_param_value<GLenum>(0);
7583 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7584 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7585 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7587 int n = g_gl_enums.get_pname_count(pname);
7590 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7591 return cStatusSoftFailure;
7594 vogl::growable_array<GLint, 16> replay_params(n + 1);
7595 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7597 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7598 GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7600 GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7602 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7605 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7606 else if (trace_params_size != sizeof(GLint) * n)
7607 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7608 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7609 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7614 case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7616 if (!benchmark_mode())
7618 GLenum target = trace_packet.get_param_value<GLenum>(0);
7619 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7620 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7621 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7623 int n = g_gl_enums.get_pname_count(pname);
7626 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7627 return cStatusSoftFailure;
7630 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7631 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7633 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7635 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7638 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7639 else if (trace_params_size != sizeof(GLuint) * n)
7640 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7641 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7642 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7647 case VOGL_ENTRYPOINT_glGetTexParameterfv:
7649 if (!benchmark_mode())
7651 GLenum target = trace_packet.get_param_value<GLenum>(0);
7652 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7653 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7654 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7656 int n = g_gl_enums.get_pname_count(pname);
7659 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7660 return cStatusSoftFailure;
7663 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7664 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7666 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7668 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7671 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7672 else if (trace_params_size != sizeof(GLfloat) * n)
7673 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7674 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7675 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7681 case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7683 status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7684 if (status != cStatusOK)
7688 case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7690 status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7691 if (status != cStatusOK)
7695 case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7697 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7698 if (status != cStatusOK)
7702 case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7704 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7705 if (status != cStatusOK)
7709 case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7711 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7712 if (status != cStatusOK)
7716 case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7718 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7719 if (status != cStatusOK)
7723 case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7725 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7726 if (status != cStatusOK)
7730 case VOGL_ENTRYPOINT_glGenLists:
7732 GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7733 GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7735 if (trace_base_handle)
7739 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7741 if ((check_gl_error()) || (!replay_base_handle))
7743 process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7744 return cStatusHardFailure;
7747 for (GLsizei i = 0; i < range; i++)
7749 GLuint trace_handle = trace_base_handle + i;
7750 GLuint replay_handle = replay_base_handle + i;
7752 if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7753 return cStatusHardFailure;
7755 if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7757 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);
7763 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7764 if (replay_base_handle)
7766 process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7768 GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7774 case VOGL_ENTRYPOINT_glCallList:
7776 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7777 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7779 GL_ENTRYPOINT(glCallList)(replay_handle);
7781 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7783 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7786 if ((status = post_draw_call()) != cStatusOK)
7791 case VOGL_ENTRYPOINT_glCallLists:
7793 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7794 GLenum type = trace_packet.get_param_value<GLenum>(1);
7795 const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7796 uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7798 uint type_size = vogl_get_gl_type_size(type);
7801 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7802 return cStatusSoftFailure;
7805 if ((n) && (!pTrace_lists))
7807 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7808 return cStatusSoftFailure;
7811 if (trace_lists_size < (type_size * n))
7813 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7814 return cStatusSoftFailure;
7817 GLuint list_base = 0;
7818 GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7820 const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7821 for (GLsizei i = 0; i < n; i++)
7823 GLint trace_handle = list_base;
7828 trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7832 case GL_UNSIGNED_BYTE:
7834 trace_handle += *pTrace_lists_ptr;
7840 trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7841 pTrace_lists_ptr += sizeof(int16);
7844 case GL_UNSIGNED_SHORT:
7846 trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7847 pTrace_lists_ptr += sizeof(uint16);
7852 trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7853 pTrace_lists_ptr += sizeof(int32);
7856 case GL_UNSIGNED_INT:
7858 trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7859 pTrace_lists_ptr += sizeof(uint32);
7864 trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7865 pTrace_lists_ptr += sizeof(float);
7870 trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7871 pTrace_lists_ptr += 2;
7876 trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7877 pTrace_lists_ptr += 3;
7882 trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7883 pTrace_lists_ptr += 4;
7888 process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7889 return cStatusSoftFailure;
7893 if (trace_handle <= 0)
7895 process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7899 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7900 GL_ENTRYPOINT(glCallList)(replay_handle);
7902 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7904 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7909 if ((status = post_draw_call()) != cStatusOK)
7914 case VOGL_ENTRYPOINT_glDeleteLists:
7916 GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7917 GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7919 for (GLsizei i = 0; i < range; i++)
7921 GLuint trace_handle = trace_list + i;
7922 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7924 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7926 process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7932 case VOGL_ENTRYPOINT_glIsList:
7934 if (!benchmark_mode())
7936 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7937 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7938 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7940 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7941 if (trace_result != replay_result)
7942 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));
7947 case VOGL_ENTRYPOINT_glNewList:
7949 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7950 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7951 GLenum mode = trace_packet.get_param_value<GLenum>(1);
7955 GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7957 if (!check_gl_error())
7959 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7961 get_context_state()->m_current_display_list_mode = mode;
7962 get_context_state()->m_current_display_list_handle = trace_handle;
7965 // TODO: Check if glNewList() failed vs the replay.
7966 // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7967 // 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.
7970 case VOGL_ENTRYPOINT_glListBase:
7972 GLuint base = trace_packet.get_param_value<GLuint>(0);
7973 GL_ENTRYPOINT(glListBase)(base);
7976 case VOGL_ENTRYPOINT_glEndList:
7978 GL_ENTRYPOINT(glEndList)();
7980 if (!get_context_state()->is_composing_display_list())
7982 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7986 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7987 process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7989 get_context_state()->m_current_display_list_mode = GL_NONE;
7990 get_context_state()->m_current_display_list_handle = -1;
7995 case VOGL_ENTRYPOINT_glFeedbackBuffer:
7997 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7998 GLenum type = trace_packet.get_param_value<GLenum>(1);
8000 if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
8001 m_pCur_context_state->m_feedback_buffer.resize(size);
8003 GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
8007 case VOGL_ENTRYPOINT_glSeparableFilter2D:
8009 GLenum target = trace_packet.get_param_value<GLenum>(0);
8010 GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
8011 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8012 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8013 GLenum format = trace_packet.get_param_value<GLenum>(4);
8014 GLenum type = trace_packet.get_param_value<GLenum>(5);
8016 const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
8017 uint row_size = trace_packet.get_param_client_memory_data_size(6);
8018 if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8020 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8021 return cStatusSoftFailure;
8024 const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8025 uint col_size = trace_packet.get_param_client_memory_data_size(7);
8026 if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8028 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8029 return cStatusSoftFailure;
8032 GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8036 case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8038 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8039 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8041 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));
8045 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8047 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8048 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8050 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));
8053 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8055 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8056 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8058 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));
8062 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8064 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8065 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8067 GL_ENTRYPOINT(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));
8070 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8072 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8073 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8075 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8076 trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8077 trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8080 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8082 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8083 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8085 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));
8088 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8090 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8091 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8093 GL_ENTRYPOINT(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));
8096 case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8098 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8099 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8101 GL_ENTRYPOINT(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));
8104 case VOGL_ENTRYPOINT_glGetTexEnvfv:
8106 if (!benchmark_mode())
8108 GLenum target = trace_packet.get_param_value<GLenum>(0);
8109 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8110 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8112 GLfloat vals[4] = { 0, 0, 0, 0 };
8114 int n = g_gl_enums.get_pname_count(pname);
8115 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8117 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8121 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8123 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8125 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8131 case VOGL_ENTRYPOINT_glGetTexEnviv:
8133 if (!benchmark_mode())
8135 GLenum target = trace_packet.get_param_value<GLenum>(0);
8136 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8137 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8139 GLint vals[4] = { 0, 0, 0, 0 };
8141 int n = g_gl_enums.get_pname_count(pname);
8142 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8144 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8148 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8150 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8152 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8158 case VOGL_ENTRYPOINT_glGetTexGendv:
8160 if (!benchmark_mode())
8162 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8163 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8164 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8166 GLdouble vals[4] = { 0, 0, 0, 0 };
8168 int n = g_gl_enums.get_pname_count(pname);
8169 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8171 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8175 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8177 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8179 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8185 case VOGL_ENTRYPOINT_glGetTexGenfv:
8187 if (!benchmark_mode())
8189 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8190 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8191 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8193 GLfloat vals[4] = { 0, 0, 0, 0 };
8195 int n = g_gl_enums.get_pname_count(pname);
8196 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8198 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8202 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8204 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8206 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8212 case VOGL_ENTRYPOINT_glGetTexGeniv:
8214 if (!benchmark_mode())
8216 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8217 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8218 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8220 GLint vals[4] = { 0, 0, 0, 0 };
8222 int n = g_gl_enums.get_pname_count(pname);
8223 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8225 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8229 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8231 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8233 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8239 case VOGL_ENTRYPOINT_glGetLightfv:
8241 if (!benchmark_mode())
8243 GLenum light = trace_packet.get_param_value<GLenum>(0);
8244 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8245 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8247 GLfloat vals[4] = { 0, 0, 0, 0 };
8249 int n = g_gl_enums.get_pname_count(pname);
8250 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8252 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8256 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8258 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8260 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8266 case VOGL_ENTRYPOINT_glGetLightiv:
8268 if (!benchmark_mode())
8270 GLenum light = trace_packet.get_param_value<GLenum>(0);
8271 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8272 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8274 GLint vals[4] = { 0, 0, 0, 0 };
8276 int n = g_gl_enums.get_pname_count(pname);
8277 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8279 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8283 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8285 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8287 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8293 case VOGL_ENTRYPOINT_glSelectBuffer:
8295 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8297 if (m_pCur_context_state->m_select_buffer.try_resize(size))
8299 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8303 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8308 case VOGL_ENTRYPOINT_glClearBufferfv:
8310 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8312 // TODO: Check params
8314 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8318 case VOGL_ENTRYPOINT_glClearBufferiv:
8320 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8322 // TODO: Check params
8324 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8328 case VOGL_ENTRYPOINT_glClearBufferuiv:
8330 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8332 // TODO: Check params
8334 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8338 case VOGL_ENTRYPOINT_glTexBuffer:
8339 case VOGL_ENTRYPOINT_glTexBufferARB:
8340 case VOGL_ENTRYPOINT_glTexBufferEXT:
8342 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8344 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8346 SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8349 case VOGL_ENTRYPOINT_glBeginConditionalRender:
8351 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8353 id = map_handle(get_shared_state()->m_queries, id);
8355 VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8358 case VOGL_ENTRYPOINT_glEndConditionalRender:
8360 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8362 VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8365 case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8367 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8369 VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8372 case VOGL_ENTRYPOINT_glEndTransformFeedback:
8374 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8376 VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8380 case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8382 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8383 VOGL_NOTE_UNUSED(pTrace_varyings);
8385 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8387 dynamic_string_array replay_varyings(count);
8389 const key_value_map &key_value_map = trace_packet.get_key_value_map();
8390 const value_to_value_hash_map &hash_map = key_value_map.get_map();
8392 for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8394 int key_index = it->first.get_int();
8396 if ((key_index >= 0) && (key_index < count))
8398 const dynamic_string *pName = it->second.get_string_ptr();
8401 replay_varyings[key_index] = pName ? *pName : "";
8409 vogl::vector<const GLchar *> str_ptrs(count);
8410 for (int i = 0; i < count; i++)
8411 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8413 GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8415 VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8419 case VOGL_ENTRYPOINT_glUniformBufferEXT:
8421 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8423 GLuint trace_program = program;
8425 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8426 location = determine_uniform_replay_location(trace_program, location);
8427 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8429 VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8432 case VOGL_ENTRYPOINT_glUniformBlockBinding:
8434 // TODO: Does any of this other stuff need to be remapped?
8435 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8437 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8439 VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8442 case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8444 // TODO - we need to hook up this extension to the tracer
8447 case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8449 // TODO - we need to hook up this extension to the tracer
8452 case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8453 case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8454 case VOGL_ENTRYPOINT_glDebugMessageControlARB:
8455 case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8460 case VOGL_ENTRYPOINT_glBitmap:
8462 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8464 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8466 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8467 pTrace_bitmap = (const GLubyte *)ptr_val;
8470 VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8474 case VOGL_ENTRYPOINT_glColorSubTable:
8476 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8478 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8480 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8481 pTrace_data = (const GLvoid *)ptr_val;
8484 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8488 case VOGL_ENTRYPOINT_glColorSubTableEXT:
8490 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8492 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8494 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8495 pTrace_data = (const GLvoid *)ptr_val;
8498 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8502 case VOGL_ENTRYPOINT_glColorTable:
8504 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8506 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8508 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8509 pTrace_table = (const GLvoid *)ptr_val;
8512 VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8516 case VOGL_ENTRYPOINT_glColorTableEXT:
8518 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8520 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8522 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8523 pTrace_table = (const GLvoid *)ptr_val;
8526 VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8530 case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8532 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8534 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8536 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8537 pTrace_image = (const GLvoid *)ptr_val;
8540 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8544 case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8546 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8548 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8550 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8551 pTrace_image = (const GLvoid *)ptr_val;
8554 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8558 case VOGL_ENTRYPOINT_glDrawPixels:
8560 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8562 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8564 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8565 pTrace_pixels = (const GLvoid *)ptr_val;
8568 VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8572 case VOGL_ENTRYPOINT_glPolygonStipple:
8574 VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8576 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8578 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8579 pTrace_mask = (const GLubyte *)ptr_val;
8582 VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8586 case VOGL_ENTRYPOINT_glTexImage1D:
8588 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8590 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8592 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8593 pTrace_pixels = (const GLvoid *)ptr_val;
8596 VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8600 case VOGL_ENTRYPOINT_glTexImage2D:
8602 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8604 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8606 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8607 pTrace_pixels = (const GLvoid *)ptr_val;
8610 VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8614 case VOGL_ENTRYPOINT_glTexImage3D:
8616 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8618 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8620 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8621 pTrace_pixels = (const GLvoid *)ptr_val;
8624 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8628 case VOGL_ENTRYPOINT_glTexImage3DEXT:
8630 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8632 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8634 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8635 pTrace_pixels = (const GLvoid *)ptr_val;
8638 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8642 case VOGL_ENTRYPOINT_glTexSubImage1D:
8644 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8646 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8648 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8649 pTrace_pixels = (const GLvoid *)ptr_val;
8652 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8656 case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8658 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8660 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8662 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8663 pTrace_pixels = (const GLvoid *)ptr_val;
8666 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8670 case VOGL_ENTRYPOINT_glTexSubImage2D:
8672 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8674 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8676 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8677 pTrace_pixels = (const GLvoid *)ptr_val;
8680 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8684 case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8686 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8688 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8690 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8691 pTrace_pixels = (const GLvoid *)ptr_val;
8694 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8698 case VOGL_ENTRYPOINT_glTexSubImage3D:
8700 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8702 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8704 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8705 pTrace_pixels = (const GLvoid *)ptr_val;
8708 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8712 case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8714 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8716 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8718 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8719 pTrace_pixels = (const GLvoid *)ptr_val;
8722 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8726 case VOGL_ENTRYPOINT_glAreTexturesResident:
8727 case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8728 case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8729 case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8730 case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8731 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8732 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8733 case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8734 case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8735 case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8736 case VOGL_ENTRYPOINT_glGetActiveUniformName:
8737 case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8738 case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8739 case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8740 case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8741 case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8742 case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8743 case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8744 case VOGL_ENTRYPOINT_glGetBooleani_v:
8745 case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8746 case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8747 case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8748 case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8749 case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8750 case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8751 case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8752 case VOGL_ENTRYPOINT_glGetColorTable:
8753 case VOGL_ENTRYPOINT_glGetColorTableEXT:
8754 case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8755 case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8756 case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8757 case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8758 case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8759 case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8760 case VOGL_ENTRYPOINT_glGetColorTableSGI:
8761 case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8762 case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8763 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8764 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8765 case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8766 case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8767 case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8768 case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8769 case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8770 case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8771 case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8772 case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8773 case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8774 case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8775 case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8776 case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8777 case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8778 case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8779 case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8780 case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8781 case VOGL_ENTRYPOINT_glGetDoublei_v:
8782 case VOGL_ENTRYPOINT_glGetFenceivNV:
8783 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8784 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8785 case VOGL_ENTRYPOINT_glGetFixedvOES:
8786 case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8787 case VOGL_ENTRYPOINT_glGetFloati_v:
8788 case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8789 case VOGL_ENTRYPOINT_glGetFragDataIndex:
8790 case VOGL_ENTRYPOINT_glGetFragDataLocation:
8791 case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8792 case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8793 case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8794 case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8795 case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8796 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8797 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8798 case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8799 case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8800 case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8801 case VOGL_ENTRYPOINT_glGetHandleARB:
8802 case VOGL_ENTRYPOINT_glGetHistogram:
8803 case VOGL_ENTRYPOINT_glGetHistogramEXT:
8804 case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8805 case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8806 case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8807 case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8808 case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8809 case VOGL_ENTRYPOINT_glGetImageHandleNV:
8810 case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8811 case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8812 case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8813 case VOGL_ENTRYPOINT_glGetInteger64i_v:
8814 case VOGL_ENTRYPOINT_glGetInteger64v:
8815 case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8816 case VOGL_ENTRYPOINT_glGetIntegeri_v:
8817 case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8818 case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8819 case VOGL_ENTRYPOINT_glGetInternalformati64v:
8820 case VOGL_ENTRYPOINT_glGetInternalformativ:
8821 case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8822 case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8823 case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8824 case VOGL_ENTRYPOINT_glGetLightxOES:
8825 case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8826 case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8827 case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8828 case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8829 case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8830 case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8831 case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8832 case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8833 case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8834 case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8835 case VOGL_ENTRYPOINT_glGetMapdv:
8836 case VOGL_ENTRYPOINT_glGetMapfv:
8837 case VOGL_ENTRYPOINT_glGetMapiv:
8838 case VOGL_ENTRYPOINT_glGetMapxvOES:
8839 case VOGL_ENTRYPOINT_glGetMaterialfv:
8840 case VOGL_ENTRYPOINT_glGetMaterialiv:
8841 case VOGL_ENTRYPOINT_glGetMaterialxOES:
8842 case VOGL_ENTRYPOINT_glGetMinmax:
8843 case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8844 case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8845 case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8846 case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8847 case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8848 case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8849 case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8850 case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8851 case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8852 case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8853 case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8854 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8855 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8856 case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8857 case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8858 case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8859 case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8860 case VOGL_ENTRYPOINT_glGetMultisamplefv:
8861 case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
8862 case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
8863 case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
8864 case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
8865 case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
8866 case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
8867 case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
8868 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
8869 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
8870 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
8871 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
8872 case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
8873 case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
8874 case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
8875 case VOGL_ENTRYPOINT_glGetNamedStringARB:
8876 case VOGL_ENTRYPOINT_glGetNamedStringivARB:
8877 case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
8878 case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
8879 case VOGL_ENTRYPOINT_glGetObjectLabel:
8880 case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
8881 case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
8882 case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8883 case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
8884 case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
8885 case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
8886 case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
8887 case VOGL_ENTRYPOINT_glGetPathCommandsNV:
8888 case VOGL_ENTRYPOINT_glGetPathCoordsNV:
8889 case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
8890 case VOGL_ENTRYPOINT_glGetPathLengthNV:
8891 case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
8892 case VOGL_ENTRYPOINT_glGetPathMetricsNV:
8893 case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
8894 case VOGL_ENTRYPOINT_glGetPathParameterivNV:
8895 case VOGL_ENTRYPOINT_glGetPathSpacingNV:
8896 case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
8897 case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
8898 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
8899 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
8900 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
8901 case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
8902 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
8903 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
8904 case VOGL_ENTRYPOINT_glGetPixelMapfv:
8905 case VOGL_ENTRYPOINT_glGetPixelMapuiv:
8906 case VOGL_ENTRYPOINT_glGetPixelMapusv:
8907 case VOGL_ENTRYPOINT_glGetPixelMapxv:
8908 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
8909 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
8910 case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
8911 case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
8912 case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
8913 case VOGL_ENTRYPOINT_glGetPointervEXT:
8914 case VOGL_ENTRYPOINT_glGetPolygonStipple:
8915 case VOGL_ENTRYPOINT_glGetProgramBinary:
8916 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
8917 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
8918 case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
8919 case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
8920 case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
8921 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
8922 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
8923 case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
8924 case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
8925 case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
8926 case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
8927 case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
8928 case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
8929 case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
8930 case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
8931 case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
8932 case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
8933 case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
8934 case VOGL_ENTRYPOINT_glGetProgramResourceName:
8935 case VOGL_ENTRYPOINT_glGetProgramResourceiv:
8936 case VOGL_ENTRYPOINT_glGetProgramStageiv:
8937 case VOGL_ENTRYPOINT_glGetProgramStringARB:
8938 case VOGL_ENTRYPOINT_glGetProgramStringNV:
8939 case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
8940 case VOGL_ENTRYPOINT_glGetProgramivNV:
8941 case VOGL_ENTRYPOINT_glGetQueryIndexediv:
8942 case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
8943 case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
8944 case VOGL_ENTRYPOINT_glGetQueryiv:
8945 case VOGL_ENTRYPOINT_glGetQueryivARB:
8946 case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
8947 case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
8948 case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
8949 case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
8950 case VOGL_ENTRYPOINT_glGetSeparableFilter:
8951 case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
8952 case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
8953 case VOGL_ENTRYPOINT_glGetShaderSource:
8954 case VOGL_ENTRYPOINT_glGetShaderSourceARB:
8955 case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
8956 case VOGL_ENTRYPOINT_glGetSubroutineIndex:
8957 case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
8958 case VOGL_ENTRYPOINT_glGetSynciv:
8959 case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
8960 case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
8961 case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
8962 case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
8963 case VOGL_ENTRYPOINT_glGetTexGenxvOES:
8964 case VOGL_ENTRYPOINT_glGetTexImage:
8965 case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
8966 case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
8967 case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
8968 case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
8969 case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
8970 case VOGL_ENTRYPOINT_glGetTextureHandleNV:
8971 case VOGL_ENTRYPOINT_glGetTextureImageEXT:
8972 case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
8973 case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
8974 case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
8975 case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
8976 case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
8977 case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
8978 case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
8979 case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
8980 case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
8981 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
8982 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
8983 case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
8984 case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
8985 case VOGL_ENTRYPOINT_glGetUniformIndices:
8986 case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
8987 case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
8988 case VOGL_ENTRYPOINT_glGetUniformdv:
8989 case VOGL_ENTRYPOINT_glGetUniformfv:
8990 case VOGL_ENTRYPOINT_glGetUniformfvARB:
8991 case VOGL_ENTRYPOINT_glGetUniformi64vNV:
8992 case VOGL_ENTRYPOINT_glGetUniformiv:
8993 case VOGL_ENTRYPOINT_glGetUniformivARB:
8994 case VOGL_ENTRYPOINT_glGetUniformui64vNV:
8995 case VOGL_ENTRYPOINT_glGetUniformuiv:
8996 case VOGL_ENTRYPOINT_glGetUniformuivEXT:
8997 case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
8998 case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
8999 case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
9000 case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
9001 case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
9002 case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
9003 case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9004 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9005 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9006 case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9007 case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9008 case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9009 case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9010 case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9011 case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9012 case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9013 case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9014 case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9015 case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9016 case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9017 case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9018 case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9019 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9020 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9021 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9022 case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9023 case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9024 case VOGL_ENTRYPOINT_glGetVideoivNV:
9025 case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9026 case VOGL_ENTRYPOINT_glGetVideouivNV:
9027 case VOGL_ENTRYPOINT_glGetnColorTableARB:
9028 case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9029 case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9030 case VOGL_ENTRYPOINT_glGetnHistogramARB:
9031 case VOGL_ENTRYPOINT_glGetnMapdvARB:
9032 case VOGL_ENTRYPOINT_glGetnMapfvARB:
9033 case VOGL_ENTRYPOINT_glGetnMapivARB:
9034 case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9035 case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9036 case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9037 case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9038 case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9039 case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9040 case VOGL_ENTRYPOINT_glGetnTexImageARB:
9041 case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9042 case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9043 case VOGL_ENTRYPOINT_glGetnUniformivARB:
9044 case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9045 case VOGL_ENTRYPOINT_glIsBufferARB:
9046 case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9047 case VOGL_ENTRYPOINT_glIsQueryARB:
9048 case VOGL_ENTRYPOINT_glIsSync:
9049 case VOGL_ENTRYPOINT_glPrioritizeTextures:
9050 case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9052 if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9054 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9056 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9062 if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9063 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);
9065 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);
9066 return cStatusSoftFailure;
9070 m_last_processed_call_counter = trace_packet.get_call_counter();
9072 if (!m_pCur_context_state->m_inside_gl_begin)
9074 if (check_gl_error())
9075 return cStatusGLError;
9078 if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9080 if ((status = post_draw_call()) != cStatusOK)
9087 //----------------------------------------------------------------------------------------------------------------------
9088 // vogl_gl_replayer::snapshot_backbuffer
9089 //----------------------------------------------------------------------------------------------------------------------
9090 void vogl_gl_replayer::snapshot_backbuffer()
9094 if (!m_pCur_context_state)
9096 vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9100 uint recorded_width = m_pWindow->get_width();
9101 uint recorded_height = m_pWindow->get_height();
9103 uint width = 0, height = 0;
9104 m_pWindow->get_actual_dimensions(width, height);
9106 VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9107 VOGL_NOTE_UNUSED(recorded_width);
9108 VOGL_NOTE_UNUSED(recorded_height);
9110 m_screenshot_buffer.resize(width * height * 3);
9112 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);
9115 process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9118 if (m_flags & cGLReplayerDumpScreenshots)
9120 size_t png_size = 0;
9121 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9123 dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9124 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9126 process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9130 vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9136 if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9138 uint64_t backbuffer_crc64;
9140 if (m_flags & cGLReplayerSumHashing)
9142 backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9146 backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9149 vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9151 if (m_backbuffer_hash_filename.has_content())
9153 FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9155 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9158 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9165 //----------------------------------------------------------------------------------------------------------------------
9166 // vogl_gl_replayer::is_valid_handle
9167 //----------------------------------------------------------------------------------------------------------------------
9168 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9175 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9177 switch (handle_namespace)
9179 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9181 VOGL_ASSERT(replay_handle32 == replay_handle);
9182 return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9184 case VOGL_NAMESPACE_FRAMEBUFFERS:
9186 VOGL_ASSERT(replay_handle32 == replay_handle);
9187 return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9189 case VOGL_NAMESPACE_TEXTURES:
9191 VOGL_ASSERT(replay_handle32 == replay_handle);
9192 return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9194 case VOGL_NAMESPACE_RENDER_BUFFERS:
9196 VOGL_ASSERT(replay_handle32 == replay_handle);
9197 return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9199 case VOGL_NAMESPACE_QUERIES:
9201 VOGL_ASSERT(replay_handle32 == replay_handle);
9202 return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9204 case VOGL_NAMESPACE_SAMPLERS:
9206 VOGL_ASSERT(replay_handle32 == replay_handle);
9207 return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9209 case VOGL_NAMESPACE_PROGRAMS:
9211 VOGL_ASSERT(replay_handle32 == replay_handle);
9212 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9214 case VOGL_NAMESPACE_SHADERS:
9216 VOGL_ASSERT(replay_handle32 == replay_handle);
9217 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9219 case VOGL_NAMESPACE_BUFFERS:
9221 VOGL_ASSERT(replay_handle32 == replay_handle);
9222 return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9224 case VOGL_NAMESPACE_SYNCS:
9226 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9227 return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9229 case VOGL_NAMESPACE_PROGRAM_ARB:
9231 VOGL_ASSERT(replay_handle32 == replay_handle);
9232 return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9243 //----------------------------------------------------------------------------------------------------------------------
9244 // vogl_gl_replayer::remap_handle
9245 //----------------------------------------------------------------------------------------------------------------------
9246 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9253 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9255 switch (handle_namespace)
9257 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9259 VOGL_ASSERT(replay_handle32 == replay_handle);
9260 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9261 return replay_handle32;
9264 case VOGL_NAMESPACE_FRAMEBUFFERS:
9266 VOGL_ASSERT(replay_handle32 == replay_handle);
9267 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9268 return replay_handle32;
9271 case VOGL_NAMESPACE_TEXTURES:
9273 VOGL_ASSERT(replay_handle32 == replay_handle);
9275 uint32 trace_handle = replay_handle32;
9276 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9277 return trace_handle;
9281 case VOGL_NAMESPACE_RENDER_BUFFERS:
9283 VOGL_ASSERT(replay_handle32 == replay_handle);
9284 GLuint trace_handle = replay_handle32;
9285 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9286 return trace_handle;
9290 case VOGL_NAMESPACE_QUERIES:
9292 VOGL_ASSERT(replay_handle32 == replay_handle);
9293 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9294 return replay_handle32;
9297 case VOGL_NAMESPACE_SAMPLERS:
9299 VOGL_ASSERT(replay_handle32 == replay_handle);
9300 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9301 return replay_handle32;
9304 case VOGL_NAMESPACE_PROGRAMS:
9306 VOGL_ASSERT(replay_handle32 == replay_handle);
9307 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9308 GLuint trace_handle = replay_handle32;
9309 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9310 return trace_handle;
9313 case VOGL_NAMESPACE_SHADERS:
9315 VOGL_ASSERT(replay_handle32 == replay_handle);
9316 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9317 GLuint trace_handle = replay_handle32;
9318 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9319 return trace_handle;
9322 case VOGL_NAMESPACE_BUFFERS:
9324 VOGL_ASSERT(replay_handle32 == replay_handle);
9325 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9326 return replay_handle32;
9329 case VOGL_NAMESPACE_SYNCS:
9331 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9333 gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9334 if (it != m_replayer.get_shared_state()->m_syncs.end())
9336 VOGL_ASSERT(it->second == replay_sync);
9342 case VOGL_NAMESPACE_PROGRAM_ARB:
9344 VOGL_ASSERT(replay_handle32 == replay_handle);
9345 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9346 return replay_handle32;
9356 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));
9360 return replay_handle;
9363 //----------------------------------------------------------------------------------------------------------------------
9364 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9365 //----------------------------------------------------------------------------------------------------------------------
9366 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9370 if ((!replay_program) || (replay_location < 0))
9371 return replay_location;
9373 GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9375 glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9376 if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9378 const glsl_program_state &state = it->second;
9380 uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9381 if (loc_it != state.m_uniform_locations.end())
9382 return loc_it->first;
9385 vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9387 return replay_location;
9390 //----------------------------------------------------------------------------------------------------------------------
9391 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9392 //----------------------------------------------------------------------------------------------------------------------
9393 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9399 uint32 handle32 = static_cast<uint32>(replay_handle);
9401 switch (handle_namespace)
9403 case VOGL_NAMESPACE_TEXTURES:
9405 VOGL_ASSERT(handle32 == replay_handle);
9406 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9409 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9420 //----------------------------------------------------------------------------------------------------------------------
9421 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9422 //----------------------------------------------------------------------------------------------------------------------
9423 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9429 uint32 handle32 = static_cast<uint32>(trace_handle);
9431 switch (handle_namespace)
9433 case VOGL_NAMESPACE_TEXTURES:
9435 VOGL_ASSERT(handle32 == trace_handle);
9436 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9439 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9450 //----------------------------------------------------------------------------------------------------------------------
9451 // vogl_replayer::determine_used_program_handles
9452 //----------------------------------------------------------------------------------------------------------------------
9453 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9457 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9460 GLint cur_program_handle = 0;
9461 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9464 if (cur_program_handle)
9465 replay_program_handles.insert(cur_program_handle);
9468 // Scan for bound programs on all contexts in this sharegroup
9469 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9470 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9472 context_state *pContext = it->second;
9473 if (pContext->m_pShared_state == pContext_shareroot)
9475 if (pContext->m_cur_replay_program)
9476 replay_program_handles.insert(pContext->m_cur_replay_program);
9480 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9482 if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9485 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9487 // 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.
9488 if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9491 GLuint trace_handle = 0;
9492 bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9493 if (!refers_to_program)
9498 // 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
9499 // 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).
9500 if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9503 uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9507 VOGL_ASSERT(utils::is_32bit(replay_handle));
9509 replay_program_handles.insert(static_cast<uint32>(replay_handle));
9512 vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9517 //----------------------------------------------------------------------------------------------------------------------
9518 // vogl_replayer::fill_replay_handle_hash_set
9519 //----------------------------------------------------------------------------------------------------------------------
9520 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)
9524 replay_handle_hash.reset();
9525 replay_handle_hash.reserve(trace_to_replay_hash.size());
9526 for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9528 // Insert replay handles into destination hash table
9529 bool success = replay_handle_hash.insert(it->second).second;
9530 VOGL_ASSERT(success);
9531 VOGL_NOTE_UNUSED(success);
9535 //----------------------------------------------------------------------------------------------------------------------
9536 // vogl_replayer::snapshot_state
9537 //----------------------------------------------------------------------------------------------------------------------
9538 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9542 timed_scope ts(VOGL_METHOD_NAME);
9544 vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9546 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,
9547 m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9549 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))
9551 vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9553 vogl_delete(pSnapshot);
9559 vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9560 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9561 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()));
9563 vogl_client_side_array_desc_vec client_side_array_ptrs;
9564 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9565 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()));
9567 vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9568 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9569 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()));
9571 pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9573 vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9575 context_hash_map::iterator it;
9576 for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9578 context_state *pContext_state = it->second;
9580 if (pContext_state->m_deleted)
9582 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));
9586 vogl_capture_context_params temp_shadow_state;
9587 vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9589 if (pContext_state->m_has_been_made_current)
9591 status_t status = switch_contexts(it->first);
9592 if (status != cStatusOK)
9594 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9598 VOGL_ASSERT(m_pCur_context_state == pContext_state);
9600 if (m_pCur_context_state->m_inside_gl_begin)
9602 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));
9603 pSnapshot->set_is_restorable(false);
9607 // Init the shadow state needed by the snapshot code.
9608 if (!m_pCur_context_state->is_root_context())
9610 // Only fill in non-shared state.
9611 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9612 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9616 pShadow_state = &m_pCur_context_state->m_shadow_state;
9618 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9620 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9621 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9622 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9625 pShadow_state->m_buffer_targets.reset();
9626 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)
9628 GLuint trace_handle = buf_it->first;
9629 GLuint replay_handle = buf_it->second;
9631 gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9632 if (target_it == get_shared_state()->m_buffer_targets.end())
9634 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);
9637 GLenum target = target_it->second;
9639 pShadow_state->m_buffer_targets.insert(replay_handle, target);
9643 pShadow_state->m_syncs.reset();
9644 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9645 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)
9647 bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9648 VOGL_ASSERT(success);
9649 VOGL_NOTE_UNUSED(success);
9652 // Program handles filter
9653 pShadow_state->m_filter_program_handles = false;
9654 pShadow_state->m_program_handles_filter.reset();
9657 // 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).
9658 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9659 if ((pTrim_packets) && (optimize_snapshot))
9661 if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9663 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9664 pShadow_state->m_program_handles_filter.clear();
9668 pShadow_state->m_filter_program_handles = true;
9672 VOGL_NOTE_UNUSED(optimize_snapshot);
9673 VOGL_NOTE_UNUSED(pTrim_packets);
9676 // ARB program targets
9677 pShadow_state->m_arb_program_targets.reset();
9678 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)
9680 GLuint trace_handle = arb_prog_it->first;
9681 GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9682 if ((!trace_handle) || (!replay_handle))
9688 GLenum target = arb_prog_it->second;
9689 pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9692 // Deal with any currently mapped buffers.
9693 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9695 pShadow_state->m_mapped_buffers = mapped_bufs;
9697 if (mapped_bufs.size())
9699 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());
9701 for (uint i = 0; i < mapped_bufs.size(); i++)
9703 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9705 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9707 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9708 VOGL_CHECK_GL_ERROR;
9710 GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9711 VOGL_CHECK_GL_ERROR;
9715 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9716 VOGL_CHECK_GL_ERROR;
9720 } // if (!m_pCur_context_state->is_root_context())
9722 } // if (pContext_state->m_has_been_made_current)
9724 if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9726 vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9730 if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9732 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9734 // Now remap any mapped buffers
9735 for (uint i = 0; i < mapped_bufs.size(); i++)
9737 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9739 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9741 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9742 VOGL_CHECK_GL_ERROR;
9746 desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9747 VOGL_CHECK_GL_ERROR;
9751 desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9752 VOGL_CHECK_GL_ERROR;
9755 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9756 VOGL_CHECK_GL_ERROR;
9762 if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9764 vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9768 vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9770 vogl_delete(pSnapshot);
9777 //----------------------------------------------------------------------------------------------------------------------
9778 // vogl_replayer::reset_state
9779 //----------------------------------------------------------------------------------------------------------------------
9780 void vogl_gl_replayer::reset_state()
9784 // Purposely does NOT destroy the cached snapshots
9786 destroy_pending_snapshot();
9789 m_pending_make_current_packet.clear();
9790 m_pending_window_resize_width = 0;
9791 m_pending_window_resize_height = 0;
9792 m_pending_window_resize_attempt_counter = 0;
9795 m_last_parsed_call_counter = -1;
9796 m_last_processed_call_counter = -1;
9797 m_at_frame_boundary = true;
9799 m_cur_trace_context = 0;
9800 m_cur_replay_context = 0;
9801 m_pCur_context_state = NULL;
9804 //if (m_pWindow->is_opened())
9805 // m_pWindow->clear_window();
9808 //----------------------------------------------------------------------------------------------------------------------
9809 // trace_to_replay_handle_remapper::is_valid_handle
9810 //----------------------------------------------------------------------------------------------------------------------
9811 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9818 uint32 from_handle32 = static_cast<uint32>(from_handle);
9820 switch (handle_namespace)
9822 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9824 VOGL_ASSERT(from_handle32 == from_handle);
9825 return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9827 case VOGL_NAMESPACE_TEXTURES:
9829 VOGL_ASSERT(from_handle32 == from_handle);
9830 return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9832 case VOGL_NAMESPACE_SAMPLERS:
9834 VOGL_ASSERT(from_handle32 == from_handle);
9835 return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9837 case VOGL_NAMESPACE_BUFFERS:
9839 VOGL_ASSERT(from_handle32 == from_handle);
9840 return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9842 case VOGL_NAMESPACE_SHADERS:
9843 case VOGL_NAMESPACE_PROGRAMS:
9845 VOGL_ASSERT(from_handle32 == from_handle);
9846 return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9848 case VOGL_NAMESPACE_FRAMEBUFFERS:
9850 VOGL_ASSERT(from_handle32 == from_handle);
9851 return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9853 case VOGL_NAMESPACE_RENDER_BUFFERS:
9855 VOGL_ASSERT(from_handle32 == from_handle);
9856 return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9858 case VOGL_NAMESPACE_QUERIES:
9860 VOGL_ASSERT(from_handle32 == from_handle);
9861 return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9863 case VOGL_NAMESPACE_SYNCS:
9865 return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
9867 case VOGL_NAMESPACE_PROGRAM_ARB:
9869 return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
9880 //----------------------------------------------------------------------------------------------------------------------
9881 // trace_to_replay_handle_remapper::remap_handle
9882 //----------------------------------------------------------------------------------------------------------------------
9883 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9890 uint32 from_handle32 = static_cast<uint32>(from_handle);
9892 switch (handle_namespace)
9894 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9896 VOGL_ASSERT(from_handle32 == from_handle);
9897 return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
9899 case VOGL_NAMESPACE_TEXTURES:
9901 VOGL_ASSERT(from_handle32 == from_handle);
9903 uint32 replay_handle = from_handle32;
9904 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
9905 return replay_handle;
9908 case VOGL_NAMESPACE_SAMPLERS:
9910 VOGL_ASSERT(from_handle32 == from_handle);
9911 return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
9913 case VOGL_NAMESPACE_BUFFERS:
9915 VOGL_ASSERT(from_handle32 == from_handle);
9916 return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
9918 case VOGL_NAMESPACE_SHADERS:
9919 case VOGL_NAMESPACE_PROGRAMS:
9921 VOGL_ASSERT(from_handle32 == from_handle);
9923 GLuint replay_handle = from_handle32;
9924 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
9925 return replay_handle;
9928 case VOGL_NAMESPACE_FRAMEBUFFERS:
9930 VOGL_ASSERT(from_handle32 == from_handle);
9931 return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
9933 case VOGL_NAMESPACE_RENDER_BUFFERS:
9935 VOGL_ASSERT(from_handle32 == from_handle);
9937 GLuint replay_handle = from_handle32;
9938 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
9939 return replay_handle;
9943 case VOGL_NAMESPACE_QUERIES:
9945 VOGL_ASSERT(from_handle32 == from_handle);
9946 return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
9948 case VOGL_NAMESPACE_SYNCS:
9950 return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
9952 case VOGL_NAMESPACE_PROGRAM_ARB:
9954 return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
9964 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
9969 //----------------------------------------------------------------------------------------------------------------------
9970 // trace_to_replay_handle_remapper::remap_location
9971 //----------------------------------------------------------------------------------------------------------------------
9972 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
9976 VOGL_NOTE_UNUSED(trace_program);
9978 // restoring declares, but doesn't need to remap
9981 return from_location;
9984 //----------------------------------------------------------------------------------------------------------------------
9985 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
9986 //----------------------------------------------------------------------------------------------------------------------
9987 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
9994 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
9995 if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
9997 m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10000 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
10003 //----------------------------------------------------------------------------------------------------------------------
10004 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10005 //----------------------------------------------------------------------------------------------------------------------
10006 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)
10010 VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10015 if (id == vogl_texcoord_pointer_array_id)
10017 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10019 if (!m_replayer.m_client_side_texcoord_data[index].size())
10021 m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10024 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10028 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10030 if (!m_replayer.m_client_side_array_data[id].size())
10032 m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10035 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10039 //----------------------------------------------------------------------------------------------------------------------
10040 // trace_to_replay_handle_remapper::declare_handle
10041 //----------------------------------------------------------------------------------------------------------------------
10042 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)
10046 if ((!from_handle) || (!to_handle))
10048 VOGL_ASSERT_ALWAYS;
10052 uint32 from_handle32 = static_cast<uint32>(from_handle);
10053 uint32 to_handle32 = static_cast<uint32>(to_handle);
10055 switch (handle_namespace)
10057 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10059 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10060 m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10063 case VOGL_NAMESPACE_TEXTURES:
10065 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10066 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10067 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);
10070 case VOGL_NAMESPACE_SAMPLERS:
10072 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10073 m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10076 case VOGL_NAMESPACE_BUFFERS:
10078 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10079 m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10080 m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10083 case VOGL_NAMESPACE_SHADERS:
10085 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10086 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10087 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);
10090 case VOGL_NAMESPACE_PROGRAMS:
10092 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10093 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10094 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);
10097 case VOGL_NAMESPACE_FRAMEBUFFERS:
10099 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10100 m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10103 case VOGL_NAMESPACE_RENDER_BUFFERS:
10105 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10106 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10107 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);
10110 case VOGL_NAMESPACE_QUERIES:
10112 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10113 m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10114 m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10117 case VOGL_NAMESPACE_SYNCS:
10119 m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10122 case VOGL_NAMESPACE_PROGRAM_ARB:
10124 m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10125 m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10136 //----------------------------------------------------------------------------------------------------------------------
10137 // trace_to_replay_handle_remapper::delete_handle_and_object
10138 //----------------------------------------------------------------------------------------------------------------------
10139 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)
10143 if ((!from_handle) || (!to_handle))
10145 VOGL_ASSERT_ALWAYS;
10149 uint32 from_handle32 = static_cast<uint32>(from_handle);
10150 uint32 to_handle32 = static_cast<uint32>(to_handle);
10151 VOGL_NOTE_UNUSED(to_handle32);
10153 switch (handle_namespace)
10155 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10157 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10158 m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10159 vogl_destroy_gl_object(handle_namespace, to_handle);
10162 case VOGL_NAMESPACE_TEXTURES:
10164 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10165 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10166 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);
10168 vogl_destroy_gl_object(handle_namespace, to_handle);
10171 case VOGL_NAMESPACE_SAMPLERS:
10173 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10174 m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10175 vogl_destroy_gl_object(handle_namespace, to_handle);
10178 case VOGL_NAMESPACE_BUFFERS:
10180 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10181 m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10182 m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10183 vogl_destroy_gl_object(handle_namespace, to_handle);
10186 case VOGL_NAMESPACE_SHADERS:
10188 m_replayer.handle_delete_shader(from_handle32);
10191 case VOGL_NAMESPACE_PROGRAMS:
10193 m_replayer.handle_delete_program(from_handle32);
10196 case VOGL_NAMESPACE_FRAMEBUFFERS:
10198 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10199 m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10200 vogl_destroy_gl_object(handle_namespace, to_handle);
10203 case VOGL_NAMESPACE_RENDER_BUFFERS:
10205 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10207 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10208 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);
10210 vogl_destroy_gl_object(handle_namespace, to_handle);
10213 case VOGL_NAMESPACE_QUERIES:
10215 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10216 m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10217 vogl_destroy_gl_object(handle_namespace, to_handle);
10220 case VOGL_NAMESPACE_SYNCS:
10222 m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10223 vogl_destroy_gl_object(handle_namespace, to_handle);
10226 case VOGL_NAMESPACE_PROGRAM_ARB:
10228 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10229 m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10230 m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10231 vogl_destroy_gl_object(handle_namespace, to_handle);
10242 //----------------------------------------------------------------------------------------------------------------------
10243 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10244 //----------------------------------------------------------------------------------------------------------------------
10245 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)
10249 GLuint check_replay_handle = 0;
10250 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10251 VOGL_ASSERT(check_replay_handle == to_program_handle);
10252 VOGL_NOTE_UNUSED(check_replay_handle);
10254 VOGL_NOTE_UNUSED(to_program_handle);
10256 glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10258 glsl_program_state &prog_state = it->second;
10260 VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10262 prog_state.m_uniform_locations.insert(from_location, to_location);
10265 //----------------------------------------------------------------------------------------------------------------------
10266 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10267 //----------------------------------------------------------------------------------------------------------------------
10268 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10274 uint32 handle32 = static_cast<uint32>(trace_handle);
10276 switch (handle_namespace)
10278 case VOGL_NAMESPACE_TEXTURES:
10280 VOGL_ASSERT(handle32 == trace_handle);
10281 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10284 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10295 //----------------------------------------------------------------------------------------------------------------------
10296 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10297 //----------------------------------------------------------------------------------------------------------------------
10298 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10304 uint32 handle32 = static_cast<uint32>(replay_handle);
10306 switch (handle_namespace)
10308 case VOGL_NAMESPACE_TEXTURES:
10310 VOGL_ASSERT(handle32 == replay_handle);
10311 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10314 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10325 //----------------------------------------------------------------------------------------------------------------------
10326 // vogl_replayer::restore_objects
10327 //----------------------------------------------------------------------------------------------------------------------
10328 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10329 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,
10330 vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10334 VOGL_NOTE_UNUSED(snapshot);
10336 if (m_flags & cGLReplayerVerboseMode)
10337 vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10340 if (m_flags & cGLReplayerVerboseMode)
10343 const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10347 for (uint i = 0; i < object_ptrs.size(); i++)
10349 const vogl_gl_object_state *pState_obj = object_ptrs[i];
10351 if (pState_obj->get_type() != state_type)
10354 GLuint64 restore_handle = 0;
10355 if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10357 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);
10358 return cStatusHardFailure;
10362 if (pState_obj->get_marked_for_deletion())
10364 objects_to_delete.push_back(pState_obj);
10367 VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10369 switch (pState_obj->get_type())
10373 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10375 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10376 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10382 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10384 if (pProg->has_link_time_snapshot())
10386 vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10387 if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10389 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);
10393 get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10397 if (m_flags & cGLReplayerVerboseMode)
10399 if ((n & 255) == 255)
10400 vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10407 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10409 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10410 if (pBuf->get_is_mapped())
10412 vogl_mapped_buffer_desc map_desc;
10413 map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10414 map_desc.m_target = pBuf->get_target();
10415 map_desc.m_offset = pBuf->get_map_ofs();
10416 map_desc.m_length = pBuf->get_map_size();
10417 map_desc.m_access = pBuf->get_map_access();
10418 map_desc.m_range = pBuf->get_is_map_range();
10420 GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10422 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10423 VOGL_CHECK_GL_ERROR;
10425 if (map_desc.m_range)
10427 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);
10428 VOGL_CHECK_GL_ERROR;
10432 map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10433 VOGL_CHECK_GL_ERROR;
10436 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10437 VOGL_CHECK_GL_ERROR;
10439 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10440 mapped_bufs.push_back(map_desc);
10450 if (m_flags & cGLReplayerVerboseMode)
10453 vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10455 vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10461 //----------------------------------------------------------------------------------------------------------------------
10462 // vogl_xfont_cache
10463 //----------------------------------------------------------------------------------------------------------------------
10464 class vogl_xfont_cache
10466 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10469 vogl_xfont_cache(Display *dpy)
10475 ~vogl_xfont_cache()
10486 for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10487 XFreeFont(m_dpy, it->second);
10491 XFontStruct *get_or_create(const char *pName)
10495 XFontStruct **ppXFont = m_xfonts.find_value(pName);
10499 XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10501 m_xfonts.insert(pName, pXFont);
10509 typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10510 xfont_map m_xfonts;
10513 //----------------------------------------------------------------------------------------------------------------------
10514 // vogl_replayer::restore_display_lists
10515 //----------------------------------------------------------------------------------------------------------------------
10516 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)
10520 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10521 VOGL_NOTE_UNUSED(snapshot);
10523 VOGL_ASSERT(m_cur_trace_context);
10527 const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10529 if (!disp_lists.size())
10532 vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10534 vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10536 const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10538 for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10540 GLuint trace_handle = it->first;
10541 const vogl_display_list &disp_list = it->second;
10545 VOGL_ASSERT_ALWAYS;
10549 GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10550 if (check_gl_error() || !replay_handle)
10551 goto handle_failure;
10553 if (disp_list.is_valid())
10555 if (disp_list.is_xfont())
10557 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10560 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);
10564 GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10569 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10571 if (check_gl_error() || !replay_handle)
10573 GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10576 goto handle_failure;
10579 const vogl_trace_packet_array &packets = disp_list.get_packets();
10581 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10583 if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10585 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);
10589 const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10591 if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10593 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);
10597 vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10599 gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10601 if (m_flags & cGLReplayerDebugMode)
10602 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10604 int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10605 int64_t prev_processed_call_counter = m_last_processed_call_counter;
10606 m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10607 m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10608 bool prev_at_frame_boundary = m_at_frame_boundary;
10610 const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10612 m_pCur_gl_packet = &m_temp2_gl_packet;
10614 vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10616 m_pCur_gl_packet = pPrev_gl_packet;
10618 m_last_parsed_call_counter = prev_parsed_call_counter;
10619 m_last_processed_call_counter = prev_processed_call_counter;
10620 m_at_frame_boundary = prev_at_frame_boundary;
10622 if (status != cStatusOK)
10624 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);
10629 // TODO: Set context state because we're currently generating a display list!
10630 if (disp_list.is_generating())
10632 VOGL_ASSERT_ALWAYS;
10635 GL_ENTRYPOINT(glEndList)();
10640 get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10642 if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10644 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);
10650 vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10655 return cStatusHardFailure;
10658 //----------------------------------------------------------------------------------------------------------------------
10659 // vogl_replayer::restore_general_state
10660 //----------------------------------------------------------------------------------------------------------------------
10661 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)
10665 VOGL_NOTE_UNUSED(snapshot);
10667 vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10668 persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10670 if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10671 return cStatusHardFailure;
10673 if (!m_pCur_context_state->m_context_info.is_core_profile())
10675 if (context_snapshot.get_texenv_state().is_valid())
10677 if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10678 return cStatusHardFailure;
10681 if (context_snapshot.get_material_state().is_valid())
10683 if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10684 return cStatusHardFailure;
10687 if (context_snapshot.get_light_state().is_valid())
10689 if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10690 return cStatusHardFailure;
10693 if (context_snapshot.get_matrix_state().is_valid())
10695 if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10696 return cStatusHardFailure;
10699 if (context_snapshot.get_polygon_stipple_state().is_valid())
10701 if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10702 return cStatusHardFailure;
10705 if (context_snapshot.get_arb_program_environment_state().is_valid())
10707 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10709 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10710 return cStatusHardFailure;
10714 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);
10719 if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10721 if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10722 return cStatusHardFailure;
10728 //----------------------------------------------------------------------------------------------------------------------
10729 // vogl_replayer::validate_program_and_shader_handle_tables
10730 //----------------------------------------------------------------------------------------------------------------------
10731 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10735 if (!m_pCur_context_state)
10738 if (!get_shared_state()->m_shadow_state.m_objs.check())
10739 vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10741 uint_vec replay_handles;
10742 get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10744 for (uint i = 0; i < replay_handles.size(); i++)
10746 GLuint replay_handle = replay_handles[i];
10747 GLuint trace_handle = replay_handle;
10748 bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10749 VOGL_ASSERT(map_succeeded);
10750 VOGL_NOTE_UNUSED(map_succeeded);
10752 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10753 VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10755 if (target == VOGL_PROGRAM_OBJECT)
10757 if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10759 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);
10762 if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10764 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);
10767 else if (target == VOGL_SHADER_OBJECT)
10769 if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10771 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);
10776 VOGL_ASSERT_ALWAYS;
10783 //----------------------------------------------------------------------------------------------------------------------
10784 // vogl_replayer::validate_textures
10785 //----------------------------------------------------------------------------------------------------------------------
10786 bool vogl_gl_replayer::validate_textures()
10790 if (!m_pCur_context_state)
10793 if (!get_shared_state()->m_shadow_state.m_textures.check())
10794 vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10796 for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10798 bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10800 bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10804 if (found_in_shadow)
10806 GLuint trace_handle = 0;
10807 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10808 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);
10813 if (!found_in_shadow)
10815 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);
10823 //----------------------------------------------------------------------------------------------------------------------
10824 // vogl_replayer::update_context_shadows
10825 //----------------------------------------------------------------------------------------------------------------------
10826 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)
10830 VOGL_NOTE_UNUSED(snapshot);
10831 VOGL_NOTE_UNUSED(context_snapshot);
10832 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10836 // Make sure shadow is good
10837 GLint actual_current_replay_program = 0;
10838 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10841 m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10842 if (!actual_current_replay_program)
10843 m_pCur_context_state->m_cur_trace_program = 0;
10846 GLuint trace_handle = actual_current_replay_program;
10847 if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10849 process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10851 m_pCur_context_state->m_cur_replay_program = 0;
10852 m_pCur_context_state->m_cur_trace_program = 0;
10856 m_pCur_context_state->m_cur_trace_program = trace_handle;
10860 check_program_binding_shadow();
10865 //----------------------------------------------------------------------------------------------------------------------
10866 // vogl_replayer::handle_marked_for_deleted_objects
10867 //----------------------------------------------------------------------------------------------------------------------
10868 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)
10872 if (m_flags & cGLReplayerVerboseMode)
10874 vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
10877 for (uint i = 0; i < objects_to_delete.size(); i++)
10879 const vogl_gl_object_state *pState_obj = objects_to_delete[i];
10881 GLuint64 trace_handle = pState_obj->get_snapshot_handle();
10882 GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
10884 if (m_flags & cGLReplayerVerboseMode)
10886 // This should be a rare/exception case so let's try to be a little paranoid.
10887 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,
10888 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10891 GLboolean object_is_still_a_name = true;
10893 switch (pState_obj->get_type())
10897 handle_delete_program(static_cast<GLuint>(trace_handle));
10899 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
10905 handle_delete_shader(static_cast<GLuint>(trace_handle));
10907 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
10913 VOGL_ASSERT_ALWAYS;
10918 // "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."
10919 // Same for shaders.
10920 if (!object_is_still_a_name)
10922 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,
10923 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10928 //----------------------------------------------------------------------------------------------------------------------
10929 // vogl_replayer::begin_applying_snapshot
10930 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
10931 //----------------------------------------------------------------------------------------------------------------------
10932 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
10936 if (!pSnapshot->is_valid())
10938 if (delete_snapshot_after_applying)
10939 vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
10941 return cStatusHardFailure;
10946 m_pPending_snapshot = pSnapshot;
10947 m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
10949 m_frame_index = pSnapshot->get_frame_index();
10950 m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
10951 m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
10952 m_at_frame_boundary = false;
10954 if (!(m_flags & cGLReplayerLockWindowDimensions))
10956 return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
10959 return process_applying_pending_snapshot();
10962 //----------------------------------------------------------------------------------------------------------------------
10963 // vogl_replayer::restore_context
10964 //----------------------------------------------------------------------------------------------------------------------
10965 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)
10969 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10970 VOGL_NOTE_UNUSED(snapshot);
10972 // TODO: This always creates with attribs, also need to support plain glXCreateContext()
10974 Display *dpy = m_pWindow->get_display();
10975 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
10977 vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
10979 GLXContext replay_share_context = remap_context(trace_share_context);
10980 if ((trace_share_context) && (!replay_share_context))
10982 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));
10983 return cStatusHardFailure;
10986 GLboolean direct = context_snapshot.get_context_desc().get_direct();
10988 vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
10990 status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
10991 context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
10992 context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
10993 if (status != cStatusOK)
10995 vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
10999 // Has this context ever been made current?
11000 if (context_snapshot.get_context_info().is_valid())
11002 context_state *pContext_state = get_trace_context_state(trace_context);
11003 if (!pContext_state)
11005 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11006 return cStatusHardFailure;
11009 GLXContext replay_context = pContext_state->m_replay_context;
11010 if (!replay_context)
11012 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11013 return cStatusHardFailure;
11016 GLXDrawable drawable = m_pWindow->get_xwindow();
11018 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11021 vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11022 return cStatusHardFailure;
11025 m_cur_trace_context = trace_context;
11026 m_cur_replay_context = replay_context;
11027 m_pCur_context_state = pContext_state;
11029 if (!handle_context_made_current())
11030 return cStatusHardFailure;
11036 //----------------------------------------------------------------------------------------------------------------------
11037 // vogl_replayer::process_applying_pending_snapshot
11038 //----------------------------------------------------------------------------------------------------------------------
11039 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11043 if (!m_pPending_snapshot)
11046 timed_scope ts(VOGL_METHOD_NAME);
11048 const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11050 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11052 m_frame_index = snapshot.get_frame_index();
11053 m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11054 m_last_processed_call_counter = snapshot.get_gl_call_counter();
11055 m_at_frame_boundary = snapshot.get_at_frame_boundary();
11057 // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11058 for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11059 m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11061 for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11062 m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11064 for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11065 m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11067 const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11069 vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11070 vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11072 status_t status = cStatusOK;
11073 uint total_contexts_restored = 0;
11074 bool restored_default_framebuffer = false;
11078 uint num_contexts_restored_in_this_pass = 0;
11080 for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11082 if (!restore_context_ptrs[context_index])
11085 const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11087 if (context_state.get_context_desc().get_trace_share_context())
11089 // Don't restore this context if its sharelist context hasn't been restored yet
11090 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11094 status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11095 if (status != cStatusOK)
11098 // Has this context ever been made current?
11099 if (context_state.get_context_info().is_valid())
11101 // 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!)
11102 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11103 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11105 if (m_flags & cGLReplayerLowLevelDebugMode)
11107 if (!validate_textures())
11108 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11111 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11113 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11115 status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11116 if (status != cStatusOK)
11119 if (m_flags & cGLReplayerLowLevelDebugMode)
11121 if (!validate_program_and_shader_handle_tables())
11122 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11124 if (!validate_textures())
11125 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11129 if (m_flags & cGLReplayerLowLevelDebugMode)
11131 if (!validate_textures())
11132 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11135 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11136 if (status != cStatusOK)
11139 // Restore default framebuffer
11140 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11142 restored_default_framebuffer = true;
11144 if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11146 vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11150 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11151 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11152 if (status != cStatusOK)
11155 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11156 if (status != cStatusOK)
11159 if (m_flags & cGLReplayerLowLevelDebugMode)
11161 if (!validate_program_and_shader_handle_tables())
11162 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11164 if (!validate_textures())
11165 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11169 num_contexts_restored_in_this_pass++;
11171 total_contexts_restored++;
11173 restore_context_ptrs[context_index] = NULL;
11176 if (!num_contexts_restored_in_this_pass)
11180 if (total_contexts_restored != snapshot.get_contexts().size())
11182 vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11186 for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11188 const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11190 if (!context_state.get_context_info().is_valid())
11193 status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11194 if (status != cStatusOK)
11196 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()));
11200 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11202 handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11205 destroy_pending_snapshot();
11216 //----------------------------------------------------------------------------------------------------------------------
11217 // vogl_gl_replayer::write_trim_file_internal
11218 //----------------------------------------------------------------------------------------------------------------------
11219 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)
11221 // Open the output trace
11222 // 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.
11223 const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11225 vogl_trace_packet trace_packet(&trace_gl_ctypes);
11227 // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11228 bool found_state_snapshot = false;
11229 dynamic_string binary_snapshot_id, text_snapshot_id;
11231 bool is_at_start_of_trace = false;
11232 VOGL_NOTE_UNUSED(is_at_start_of_trace);
11234 int demarcation_packet_index = -1;
11235 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11237 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11238 if (packet_type != cTSPTGLEntrypoint)
11241 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11243 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11244 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11247 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11249 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11253 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11254 if (cmd == cITCRDemarcation)
11256 is_at_start_of_trace = true;
11257 demarcation_packet_index = packet_index;
11259 else if (cmd == cITCRKeyValueMap)
11261 key_value_map &kvm = trace_packet.get_key_value_map();
11263 dynamic_string cmd_type(kvm.get_string("command_type"));
11265 if (cmd_type == "state_snapshot")
11267 found_state_snapshot = true;
11269 text_snapshot_id = kvm.get_string("id");
11270 binary_snapshot_id = kvm.get_string("binary_id");
11275 vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11276 if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11278 console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11282 if (found_state_snapshot)
11284 // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11285 if (trace_reader.get_archive_blob_manager().is_initialized())
11287 dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11288 for (uint i = 0; i < blob_files.size(); i++)
11290 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11293 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11295 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11297 vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11305 // Copy over the source trace's backtrace map, machine info, etc. files.
11306 if (trace_reader.get_archive_blob_manager().is_initialized())
11308 // compiler_info.json
11309 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);
11310 // machine_info.json
11311 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);
11312 // backtrace_map_syms.json
11313 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);
11314 // backtrace_map_addrs.json
11315 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);
11318 vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11320 if (!pTrim_snapshot.get())
11322 console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11326 pTrim_snapshot->set_frame_index(0);
11329 if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11331 console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11332 trace_writer.close();
11333 file_utils::delete_file(trim_filename.get_ptr());
11337 vogl::vector<char> snapshot_data;
11338 doc.serialize(snapshot_data, true, 0, false);
11340 uint8_vec binary_snapshot_data;
11341 doc.binary_serialize(binary_snapshot_data);
11343 pTrim_snapshot.reset();
11345 // Write the state_snapshot file to the trace archive
11346 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));
11347 if (snapshot_id.is_empty())
11349 console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11350 trace_writer.close();
11351 file_utils::delete_file(trim_filename.get_ptr());
11356 *pSnapshot_id = snapshot_id;
11358 snapshot_data.clear();
11360 // Write the binary_state_snapshot file to the trace archive
11361 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));
11362 if (binary_snapshot_id.is_empty())
11364 console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11365 trace_writer.close();
11366 file_utils::delete_file(trim_filename.get_ptr());
11370 binary_snapshot_data.clear();
11372 key_value_map snapshot_key_value_map;
11373 snapshot_key_value_map.insert("command_type", "state_snapshot");
11374 snapshot_key_value_map.insert("id", snapshot_id);
11375 snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11377 dynamic_stream snapshot_stream(0);
11378 if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11380 console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11381 trace_writer.close();
11382 file_utils::delete_file(trim_filename.get_ptr());
11386 if (demarcation_packet_index >= 0)
11388 trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11389 demarcation_packet_index++;
11393 dynamic_stream demarcation_stream(0);
11394 vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11396 // Screw the ctypes packet, it's only used for debugging right now anyway.
11397 trim_packets.insert(0, snapshot_stream.get_buf());
11398 trim_packets.insert(1, demarcation_stream.get_buf());
11402 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11404 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11406 const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11408 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11409 if (packet_type == cTSPTEOF)
11411 else if (packet_type != cTSPTGLEntrypoint)
11413 VOGL_ASSERT_ALWAYS;
11416 if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11418 console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11419 trace_writer.close();
11420 file_utils::delete_file(trim_filename.get_ptr());
11425 bool success = trace_writer.close();
11427 console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11429 console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11434 //----------------------------------------------------------------------------------------------------------------------
11435 // vogl_gl_replayer::write_trim_file
11436 //----------------------------------------------------------------------------------------------------------------------
11437 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)
11443 console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11447 bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11449 if ((!from_start_of_frame) || (!trim_len))
11450 flags &= ~cWriteTrimFileOptimizeSnapshot;
11452 const uint trim_frame = static_cast<uint>(get_frame_index());
11453 const int64_t trim_call_counter = get_last_parsed_call_counter();
11455 // Read the desired packets from the source trace file
11456 vogl_trace_packet_array trim_packets;
11458 if ((trim_len) || (!trim_frame))
11460 console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11462 uint frames_to_read = trim_len;
11463 if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11464 frames_to_read = 1;
11466 uint actual_trim_len = 0;
11467 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);
11468 if (read_packets_status == vogl_trace_file_reader::cFailed)
11470 console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11474 if (actual_trim_len != frames_to_read)
11476 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);
11479 if (from_start_of_frame)
11481 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);
11483 if ((!trim_frame) && (!trim_len))
11485 // 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.
11486 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11488 vogl_trace_packet_array new_trim_packets;
11490 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11492 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11494 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11495 if (packet_type != cTSPTGLEntrypoint)
11498 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11500 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11501 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11504 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11506 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11510 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11512 new_trim_packets.push_back(packet_buf);
11514 if (cmd == cITCRDemarcation)
11518 trim_packets.swap(new_trim_packets);
11521 else if (trim_call_counter >= 0)
11523 uint orig_num_packets = trim_packets.size();
11524 uint total_erased_packets = 0;
11526 // Remove any calls before the current one.
11527 for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11529 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11532 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11534 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11536 trim_packets.erase(static_cast<uint>(packet_index));
11539 total_erased_packets++;
11543 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());
11547 if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11549 console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11551 file_utils::delete_file(trim_filename.get_ptr());