1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_gl_replayer.cpp
27 #include "vogl_gl_replayer.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_sync_object.h"
30 #include "vogl_trace_file_writer.h"
31 #include "vogl_texture_format.h"
32 #include "gl_glx_replay_helper_macros.inc"
33 #include "vogl_backtrace.h"
35 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
36 #include "vogl_miniz.h"
38 #include "vogl_timer.h"
39 #include "vogl_file_utils.h"
41 #include "vogl_vector.h"
43 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC 129
44 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC 0x12345678
45 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC -999999.0f
47 //----------------------------------------------------------------------------------------------------------------------
48 // glInterleavedArrays helper table
49 //----------------------------------------------------------------------------------------------------------------------
50 struct interleaved_array_desc_entry_t
66 #define _2f (sizeof(GLfloat) * 2)
67 #define _3f (sizeof(GLfloat) * 3)
68 #define _4f (sizeof(GLfloat) * 4)
69 #define _5f (sizeof(GLfloat) * 5)
70 #define _6f (sizeof(GLfloat) * 6)
71 #define _7f (sizeof(GLfloat) * 7)
72 #define _8f (sizeof(GLfloat) * 8)
73 #define _9f (sizeof(GLfloat) * 9)
74 #define _10f (sizeof(GLfloat) * 10)
75 #define _11f (sizeof(GLfloat) * 11)
76 #define _12f (sizeof(GLfloat) * 12)
77 #define _15f (sizeof(GLfloat) * 15)
78 #define _c (sizeof(GL_UNSIGNED_BYTE) * 4)
80 static const interleaved_array_desc_entry_t vogl_g_interleaved_array_descs[] =
82 // format et ec en st sc sv tc pc pn pv s
83 { GL_V2F, false, false, false, 0, 0, 2, 0, 0, 0, 0, _2f },
84 { GL_V3F, false, false, false, 0, 0, 3, 0, 0, 0, 0, _3f },
85 { GL_C4UB_V2F, false, true, false, 0, 4, 2, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _2f },
86 { GL_C4UB_V3F, false, true, false, 0, 4, 3, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _3f },
87 { GL_C3F_V3F, false, true, false, 0, 3, 3, GL_FLOAT, 0, 0, _3f, _6f },
88 { GL_N3F_V3F, false, false, true, 0, 0, 3, 0, 0, 0, _3f, _6f },
89 { GL_C4F_N3F_V3F, false, true, true, 0, 4, 3, GL_FLOAT, 0, _4f, _7f, _10f },
90 { GL_T2F_V3F, true, false, false, 2, 0, 3, 0, 0, 0, _2f, _5f },
91 { GL_T4F_V4F, true, false, false, 4, 0, 4, 0, 0, 0, _4f, _8f },
92 { GL_T2F_C4UB_V3F, true, true, false, 2, 4, 3, GL_UNSIGNED_BYTE, _2f, 0, _c + _2f, _c + _5f },
93 { GL_T2F_C3F_V3F, true, true, false, 2, 3, 3, GL_FLOAT, 0, _2f, _5f, _8f },
94 { GL_T2F_N3F_V3F, true, false, true, 2, 0, 3, 0, 0, _2f, _5f, _8f },
95 { GL_T2F_C4F_N3F_V3F, true, true, true, 2, 4, 3, GL_FLOAT, _2f, _6f, _9f, _12f },
96 { GL_T4F_C4F_N3F_V4F, true, true, true, 4, 4, 4, GL_FLOAT, _4f, _8f, _11f, _15f }
113 #define VOGL_INTERLEAVED_ARRAY_SIZE (sizeof(vogl_g_interleaved_array_descs) / sizeof(vogl_g_interleaved_array_descs[0]))
115 //----------------------------------------------------------------------------------------------------------------------
116 // vogl_replayer::vogl_replayer
117 //----------------------------------------------------------------------------------------------------------------------
118 vogl_gl_replayer::vogl_gl_replayer()
120 m_swap_sleep_time(0),
121 m_dump_framebuffer_on_draw_prefix("screenshot"),
122 m_screenshot_prefix("screenshot"),
123 m_dump_framebuffer_on_draw_frame_index(-1),
124 m_dump_framebuffer_on_draw_first_gl_call_index(-1),
125 m_dump_framebuffer_on_draw_last_gl_call_index(-1),
126 m_ctypes_packet(&m_trace_gl_ctypes),
127 m_trace_pointer_size_in_bytes(0),
128 m_trace_pointer_size_in_uints(0),
129 m_temp_gl_packet(&m_trace_gl_ctypes),
130 m_temp2_gl_packet(&m_trace_gl_ctypes),
131 m_pCur_gl_packet(NULL),
133 m_pending_make_current_packet(&m_trace_gl_ctypes),
134 m_pending_window_resize_width(0),
135 m_pending_window_resize_height(0),
136 m_pending_window_resize_attempt_counter(false),
139 m_last_parsed_call_counter(-1),
140 m_last_processed_call_counter(-1),
141 m_cur_trace_context(0),
142 m_cur_replay_context(NULL),
143 m_pCur_context_state(NULL),
144 m_frame_draw_counter(0),
145 m_frame_draw_counter_kill_threshold(cUINT64_MAX),
147 m_pBlob_manager(NULL),
148 m_pPending_snapshot(NULL),
149 m_delete_pending_snapshot_after_applying(false),
150 m_replay_to_trace_remapper(*this)
154 m_trace_gl_ctypes.init();
157 //----------------------------------------------------------------------------------------------------------------------
158 // vogl_replayer::~vogl_replayer
159 //----------------------------------------------------------------------------------------------------------------------
160 vogl_gl_replayer::~vogl_gl_replayer()
167 //----------------------------------------------------------------------------------------------------------------------
168 // vogl_replayer::init
169 //----------------------------------------------------------------------------------------------------------------------
170 bool vogl_gl_replayer::init(uint flags, vogl_replay_window *pWindow, const vogl_trace_stream_start_of_file_packet &sof_packet, const vogl_blob_manager &blob_manager)
177 if ((!pWindow) || (!pWindow->is_opened()))
183 if ((sof_packet.m_pointer_sizes != sizeof(uint32)) && (sof_packet.m_pointer_sizes != sizeof(uint64_t)))
185 vogl_error_printf("%s: Invalid trace pointer size (%u)\n", VOGL_METHOD_NAME, m_sof_packet.m_pointer_sizes);
189 m_pBlob_manager = &blob_manager;
193 m_sof_packet = sof_packet;
194 m_trace_pointer_size_in_bytes = m_sof_packet.m_pointer_sizes;
195 m_trace_pointer_size_in_uints = m_sof_packet.m_pointer_sizes / sizeof(uint);
197 m_trace_gl_ctypes.init();
198 m_trace_gl_ctypes.change_pointer_sizes(m_trace_pointer_size_in_bytes);
200 if (!m_pWindow->is_opened())
202 const uint initial_window_width = 1024;
203 const uint initial_window_height = 768;
204 if (!m_pWindow->open(initial_window_width, initial_window_height))
206 vogl_error_printf("%s: Failed opening window!\n", VOGL_METHOD_NAME);
211 m_pCur_gl_packet = NULL;
215 m_last_parsed_call_counter = 0;
216 m_last_processed_call_counter = 0;
218 m_pending_make_current_packet.clear();
219 m_pending_window_resize_width = 0;
220 m_pending_window_resize_height = 0;
221 m_pending_window_resize_attempt_counter = 0;
223 m_at_frame_boundary = true;
225 m_cur_trace_context = 0;
226 m_cur_replay_context = 0;
227 m_pCur_context_state = NULL;
231 m_frame_draw_counter = 0;
232 m_frame_draw_counter_kill_threshold = cUINT64_MAX;
239 //----------------------------------------------------------------------------------------------------------------------
240 // vogl_replayer::deinit
241 //----------------------------------------------------------------------------------------------------------------------
242 void vogl_gl_replayer::deinit()
246 destroy_pending_snapshot();
249 // TODO: Make a 1st class snapshot cache class
250 for (uint i = 0; i < m_snapshots.size(); i++)
251 vogl_delete(m_snapshots[i].m_pSnapshot);
254 m_ctypes_packet.reset();
256 m_pCur_gl_packet = NULL;
260 m_last_parsed_call_counter = 0;
261 m_last_processed_call_counter = 0;
263 m_pending_make_current_packet.clear();
264 m_pending_window_resize_width = 0;
265 m_pending_window_resize_height = 0;
266 m_pending_window_resize_attempt_counter = 0;
268 m_at_frame_boundary = true;
270 m_cur_trace_context = 0;
271 m_cur_replay_context = 0;
272 m_pCur_context_state = NULL;
274 m_frame_draw_counter = 0;
275 m_frame_draw_counter_kill_threshold = cUINT32_MAX;
277 m_pBlob_manager = NULL;
280 m_swap_sleep_time = 0;
281 m_dump_framebuffer_on_draw_prefix = "screenshot";
282 m_screenshot_prefix = "screenshot";
283 m_backbuffer_hash_filename.clear();
284 m_dump_framebuffer_on_draw_frame_index = -1;
285 m_dump_framebuffer_on_draw_first_gl_call_index = -1;
286 m_dump_framebuffer_on_draw_last_gl_call_index = -1;
288 m_dump_frontbuffer_filename.clear();
293 //----------------------------------------------------------------------------------------------------------------------
294 // vogl_gl_replayer::dump_trace_gl_packet_debug_info
295 //----------------------------------------------------------------------------------------------------------------------
296 void vogl_gl_replayer::dump_trace_gl_packet_debug_info(const vogl_trace_gl_entrypoint_packet &gl_packet)
300 vogl_debug_printf("Trace packet: Total size %u, Param size: %u, Client mem size %u, Name value size %u, call %" PRIu64 ", ID: %s (%u), Thread ID: 0x%" PRIX64 ", Trace Context: 0x%" PRIX64 "\n",
302 gl_packet.m_param_size,
303 gl_packet.m_client_memory_size,
304 gl_packet.m_name_value_map_size,
305 gl_packet.m_call_counter,
306 g_vogl_entrypoint_descs[gl_packet.m_entrypoint_id].m_pName,
307 gl_packet.m_entrypoint_id,
308 gl_packet.m_thread_id,
309 gl_packet.m_context_handle);
312 //----------------------------------------------------------------------------------------------------------------------
313 // vogl_gl_replayer::dump_packet_as_func_call
314 //----------------------------------------------------------------------------------------------------------------------
315 void vogl_gl_replayer::dump_packet_as_func_call(const vogl_trace_packet& trace_packet)
321 if (!trace_packet.pretty_print(str, false))
322 vogl_error_printf("%s: packet pretty print failed!\n", VOGL_METHOD_NAME);
324 vogl_debug_printf("%s\n", str.get_ptr());
327 //----------------------------------------------------------------------------------------------------------------------
328 // vogl_replayer::process_next_packet
329 //----------------------------------------------------------------------------------------------------------------------
330 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(const vogl_trace_packet &gl_packet)
332 // TODO: Fix const correctness
333 return process_gl_entrypoint_packet((vogl_trace_packet &)gl_packet);
336 //----------------------------------------------------------------------------------------------------------------------
337 // vogl_replayer::process_next_packet
338 //----------------------------------------------------------------------------------------------------------------------
339 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(vogl_trace_file_reader &trace_reader)
343 vogl_trace_file_reader::trace_file_reader_status_t read_status = trace_reader.read_next_packet();
344 if (read_status == vogl_trace_file_reader::cEOF)
346 vogl_message_printf("At trace file EOF\n");
349 else if (read_status != vogl_trace_file_reader::cOK)
351 vogl_error_printf("Failed reading from trace file\n");
352 return cStatusHardFailure;
355 status_t status = cStatusOK;
357 switch (trace_reader.get_packet_type())
364 case cTSPTGLEntrypoint:
366 if (!m_temp_gl_packet.deserialize(trace_reader.get_packet_buf().get_ptr(), trace_reader.get_packet_buf().size(), false))
368 vogl_error_printf("Failed deserializing GL entrypoint packet\n");
369 status = cStatusHardFailure;
373 status = process_next_packet(m_temp_gl_packet);
379 vogl_message_printf("Encountered EOF packet in trace file\n");
380 status = cStatusAtEOF;
385 vogl_error_printf("Encountered unknown packet type in trace file\n");
386 status = cStatusSoftFailure;
393 vogl_error_printf("%s: %s failure processing GL entrypoint packet\n", VOGL_METHOD_NAME, (status == cStatusHardFailure) ? "Hard" : "Soft");
399 //----------------------------------------------------------------------------------------------------------------------
400 // vogl_replayer::process_pending_window_resize
401 //----------------------------------------------------------------------------------------------------------------------
402 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_window_resize(bool *pApplied_snapshot)
406 if (pApplied_snapshot)
407 *pApplied_snapshot = false;
409 status_t status = cStatusOK;
411 if (get_has_pending_window_resize())
413 status = process_frame_check_for_pending_window_resize();
414 if (status != cStatusOK)
418 if (m_pPending_snapshot)
420 if (pApplied_snapshot)
421 *pApplied_snapshot = true;
423 status_t status = process_applying_pending_snapshot();
424 if (status != cStatusOK)
431 //----------------------------------------------------------------------------------------------------------------------
432 // vogl_replayer::process_frame
433 //----------------------------------------------------------------------------------------------------------------------
434 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame(vogl_trace_file_reader &trace_reader)
438 status_t status = cStatusOK;
442 status = process_next_packet(trace_reader);
443 if ((status == cStatusNextFrame) || (status == cStatusResizeWindow) || (status == cStatusAtEOF) || (status == cStatusHardFailure))
450 //----------------------------------------------------------------------------------------------------------------------
451 // vogl_replayer::process_event
452 //----------------------------------------------------------------------------------------------------------------------
453 bool vogl_gl_replayer::update_window_dimensions()
457 m_pWindow->update_dimensions();
462 //----------------------------------------------------------------------------------------------------------------------
463 // vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap
464 //----------------------------------------------------------------------------------------------------------------------
465 bool vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap(const dynamic_string &filename)
467 m_dump_frontbuffer_filename = filename;
472 //----------------------------------------------------------------------------------------------------------------------
473 // vogl_gl_replayer::dump_frontbuffer_to_file
474 //----------------------------------------------------------------------------------------------------------------------
475 bool vogl_gl_replayer::dump_frontbuffer_to_file(const dynamic_string &filename)
477 if ((!m_is_valid) || (!m_pWindow))
483 uint width = 0, height = 0;
484 m_pWindow->get_actual_dimensions(width, height);
486 m_screenshot_buffer.resize(width * height * 3);
488 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_FRONT);
491 vogl_error_printf("%s: Failed calling glReadPixels() to take frontbuffer screenshot!\n", VOGL_METHOD_NAME);
496 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
498 success = file_utils::write_buf_to_file(filename.get_ptr(), pPNG_data, png_size);
501 vogl_error_printf("%s: Failed writing PNG screenshot to file \"%s\"\n", filename.get_ptr(), VOGL_METHOD_NAME);
505 vogl_message_printf("Wrote PNG screenshot to file \"%s\"\n", filename.get_ptr());
513 //----------------------------------------------------------------------------------------------------------------------
514 // vogl_replayer::trigger_pending_window_resize
515 //----------------------------------------------------------------------------------------------------------------------
516 vogl_gl_replayer::status_t vogl_gl_replayer::trigger_pending_window_resize(uint win_width, uint win_height)
520 m_pending_window_resize_width = win_width;
521 m_pending_window_resize_height = win_height;
522 m_pending_window_resize_attempt_counter = 0;
523 m_time_since_pending_window_resize.start();
525 m_pWindow->resize(win_width, win_height);
527 if (m_flags & cGLReplayerVerboseMode)
528 vogl_debug_printf("%s: Waiting for window to resize to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
530 return cStatusResizeWindow;
533 //----------------------------------------------------------------------------------------------------------------------
534 // vogl_replayer::clear_pending_window_resize
535 //----------------------------------------------------------------------------------------------------------------------
536 void vogl_gl_replayer::clear_pending_window_resize()
540 m_pending_window_resize_width = 0;
541 m_pending_window_resize_height = 0;
542 m_pending_window_resize_attempt_counter = 0;
545 //----------------------------------------------------------------------------------------------------------------------
546 // vogl_replayer::process_frame_check_for_pending_window_resize
547 //----------------------------------------------------------------------------------------------------------------------
548 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame_check_for_pending_window_resize()
552 const uint cMaxSecsToWait = 5;
554 if (!get_has_pending_window_resize())
557 if (m_pending_window_resize_attempt_counter >= cMaxSecsToWait)
559 vogl_warning_printf("Waited too long for window to resize to %ux%u, giving up and continuing replay\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
561 clear_pending_window_resize();
566 uint win_width = 0, win_height = 0;
567 m_pWindow->get_actual_dimensions(win_width, win_height);
569 if ((win_width != get_pending_window_resize_width()) ||
570 (win_height != get_pending_winow_resize_height()))
572 if (m_time_since_pending_window_resize.get_elapsed_secs() < 1.0f)
574 // sleep 1ms, then retry
576 return cStatusResizeWindow;
579 // What could possibly go wrong?
580 m_pending_window_resize_attempt_counter++;
581 if (m_pending_window_resize_attempt_counter < cMaxSecsToWait)
583 m_pWindow->resize(get_pending_window_resize_width(), get_pending_winow_resize_height());
585 m_time_since_pending_window_resize.start();
587 vogl_warning_printf("Waiting up to 5 secs for window to resize to %ux%u\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
588 return cStatusResizeWindow;
592 clear_pending_window_resize();
593 m_pWindow->update_dimensions();
598 //----------------------------------------------------------------------------------------------------------------------
599 // vogl_replayer::destroy_pending_snapshot
600 //----------------------------------------------------------------------------------------------------------------------
601 void vogl_gl_replayer::destroy_pending_snapshot()
605 if (m_pPending_snapshot)
607 if (m_delete_pending_snapshot_after_applying)
609 // Ensure the snapshot cache can't be pointing to the snapshot, just to be safe.
610 // TODO: Make this a real class damn it.
611 for (uint i = 0; i < m_snapshots.size(); i++)
613 if (m_snapshots[i].m_pSnapshot == m_pPending_snapshot)
615 m_snapshots.erase(i);
620 vogl_delete(const_cast<vogl_gl_state_snapshot *>(m_pPending_snapshot));
623 m_pPending_snapshot = NULL;
626 m_delete_pending_snapshot_after_applying = false;
629 //----------------------------------------------------------------------------------------------------------------------
630 // vogl_replayer::check_gl_error
631 // Returns *true* on error, just like vogl_check_gl_error()
632 //----------------------------------------------------------------------------------------------------------------------
633 bool vogl_gl_replayer::check_gl_error_internal(bool quietly, const char *pFile, uint line, const char *pFunc)
640 // http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
641 // "Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
642 GLenum gl_err = GL_ENTRYPOINT(glGetError)();
643 if (gl_err == GL_NO_ERROR)
648 process_entrypoint_warning("%s: GL error: 0x%08X (%u): %s (Called from File: %s Line: %u Func: %s)\n", VOGL_METHOD_NAME, gl_err, gl_err, g_gl_enums.find_name("ErrorCode", gl_err), pFile ? pFile : "?", line, pFunc ? pFunc : "?");
657 //----------------------------------------------------------------------------------------------------------------------
658 // vogl_replayer::clear_contexts
659 //----------------------------------------------------------------------------------------------------------------------
660 void vogl_gl_replayer::clear_contexts()
664 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
666 context_state *pContext_state = it->second;
668 vogl_delete(pContext_state);
673 m_cur_trace_context = 0;
674 m_cur_replay_context = NULL;
675 m_pCur_context_state = NULL;
678 //----------------------------------------------------------------------------------------------------------------------
679 // vogl_replayer::destroy_contexts
680 //----------------------------------------------------------------------------------------------------------------------
681 void vogl_gl_replayer::destroy_contexts()
685 if ((m_contexts.size()) && (m_pWindow->get_display()) && (GL_ENTRYPOINT(glXMakeCurrent)) && (GL_ENTRYPOINT(glXDestroyContext)))
687 GL_ENTRYPOINT(glXMakeCurrent)(m_pWindow->get_display(), (GLXDrawable)NULL, NULL);
689 vogl::vector<context_state *> contexts_to_destroy;
690 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
691 contexts_to_destroy.push_back(it->second);
693 // Delete "tail" contexts (ones that are not referenced by any other context) in sharegroups first.
694 while (contexts_to_destroy.size())
696 for (int i = 0; i < static_cast<int>(contexts_to_destroy.size()); i++)
698 context_state *pContext_state = contexts_to_destroy[i];
700 vogl_trace_ptr_value trace_context = pContext_state->m_context_desc.get_trace_context();
702 bool skip_context = false;
703 for (int j = 0; j < static_cast<int>(contexts_to_destroy.size()); j++)
708 if (contexts_to_destroy[j]->m_context_desc.get_trace_share_context() == trace_context)
718 // This context may have been the sharegroup's root and could have been already deleted.
719 if (!pContext_state->m_deleted)
721 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), pContext_state->m_replay_context);
724 contexts_to_destroy.erase(i);
733 //----------------------------------------------------------------------------------------------------------------------
734 // vogl_replayer::define_new_context
735 //----------------------------------------------------------------------------------------------------------------------
736 vogl_gl_replayer::context_state *vogl_gl_replayer::define_new_context(
737 vogl_trace_context_ptr_value trace_context, GLXContext replay_context, vogl_trace_context_ptr_value trace_share_context, GLboolean direct, gl_entrypoint_id_t creation_func, const int *pAttrib_list, uint attrib_list_size)
741 if ((!trace_context) || (!replay_context))
747 context_state *pContext_state = vogl_new(context_state, *this);
749 pContext_state->m_trace_context = trace_context;
750 pContext_state->m_replay_context = replay_context;
752 pContext_state->m_context_desc.init(creation_func, direct, trace_context, trace_share_context, vogl_context_attribs(pAttrib_list, attrib_list_size));
754 if (trace_share_context)
756 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
758 if (trace_share_context == it->first)
760 context_state *pShare_context = it->second;
761 while (!pShare_context->is_root_context())
762 pShare_context = pShare_context->m_pShared_state;
764 pContext_state->m_pShared_state = pShare_context;
765 pContext_state->m_pShared_state->m_ref_count++;
771 if (!pContext_state->m_pShared_state)
773 process_entrypoint_error("%s: Unable to find trace share context handle 0x%" PRIX64 "!\n", VOGL_METHOD_NAME, trace_share_context);
777 m_contexts.insert(trace_context, pContext_state);
779 return pContext_state;
782 //----------------------------------------------------------------------------------------------------------------------
783 // vogl_replayer::remap_context
784 //----------------------------------------------------------------------------------------------------------------------
785 GLXContext vogl_gl_replayer::remap_context(vogl_trace_context_ptr_value trace_context)
792 context_hash_map::iterator it = m_contexts.find(trace_context);
793 return (it == m_contexts.end()) ? NULL : it->second->m_replay_context;
796 //----------------------------------------------------------------------------------------------------------------------
797 // vogl_replayer::destroy_context
798 //----------------------------------------------------------------------------------------------------------------------
799 bool vogl_gl_replayer::destroy_context(vogl_trace_context_ptr_value trace_context)
803 VOGL_ASSERT(trace_context);
805 context_hash_map::iterator it = m_contexts.find(trace_context);
806 if (it == m_contexts.end())
809 context_state *pContext_state = it->second;
810 VOGL_ASSERT(pContext_state->m_ref_count >= 1);
811 VOGL_ASSERT(!pContext_state->m_deleted);
813 if (pContext_state->is_share_context())
815 VOGL_ASSERT(pContext_state->m_ref_count == 1);
817 context_state *pShare_context = pContext_state->m_pShared_state;
818 VOGL_ASSERT(pShare_context->m_ref_count >= 1);
820 pShare_context->m_ref_count--;
821 if (!pShare_context->m_ref_count)
823 VOGL_ASSERT(pShare_context->m_deleted);
825 vogl_trace_context_ptr_value trace_share_context = pShare_context->m_context_desc.get_trace_context();
827 vogl_delete(pShare_context);
829 bool removed = m_contexts.erase(trace_share_context);
830 VOGL_NOTE_UNUSED(removed);
831 VOGL_ASSERT(removed);
834 vogl_delete(pContext_state);
836 bool removed = m_contexts.erase(trace_context);
837 VOGL_NOTE_UNUSED(removed);
838 VOGL_ASSERT(removed);
842 pContext_state->m_deleted = true;
843 pContext_state->m_ref_count--;
845 if (!pContext_state->m_ref_count)
849 vogl_delete(pContext_state);
851 bool removed = m_contexts.erase(trace_context);
852 VOGL_NOTE_UNUSED(removed);
853 VOGL_ASSERT(removed);
860 //----------------------------------------------------------------------------------------------------------------------
861 // vogl_replayer::set_client_side_array_data
862 // glVertexPointer, glNormalPointer, etc. client side data
863 //----------------------------------------------------------------------------------------------------------------------
864 bool vogl_gl_replayer::set_client_side_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
868 // TODO: Add early out
869 GLint prev_client_active_texture = 0;
870 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
872 const uint tex_coords = math::minimum<uint>(m_pCur_context_state->m_context_info.is_core_profile() ? m_pCur_context_state->m_context_info.get_max_texture_units() : m_pCur_context_state->m_context_info.get_max_texture_coords(), VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS);
874 for (uint client_array_iter = 0; client_array_iter < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_array_iter++)
876 const vogl_client_side_array_desc_t &desc = g_vogl_client_side_array_descs[client_array_iter];
878 const bool is_texcoord_array = (client_array_iter == vogl_texcoord_pointer_array_id);
881 uint base_key_index = 0x1000 + client_array_iter;
883 // Special case texcoord pointers, which are accessed via the client active texture.
884 if (is_texcoord_array)
887 base_key_index = 0x2000;
890 for (uint inner_iter = 0; inner_iter < n; inner_iter++)
892 uint key_index = base_key_index + inner_iter;
894 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(key_index));
895 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
899 if (is_texcoord_array)
901 GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + inner_iter);
904 GLboolean is_enabled = GL_ENTRYPOINT(glIsEnabled)(desc.m_is_enabled);
909 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_binding, &binding);
914 GL_ENTRYPOINT(glGetPointerv)(desc.m_get_pointer, &ptr);
918 uint8_vec &array_data = is_texcoord_array ? m_client_side_texcoord_data[inner_iter] : m_client_side_array_data[client_array_iter];
919 if (ptr != array_data.get_ptr())
925 GLint type = GL_BOOL;
928 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_type, &type);
932 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_stride, &stride);
937 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_size, &size);
940 uint type_size = vogl_get_gl_type_size(type);
943 process_entrypoint_error("%s: Can't determine type size of enabled client side array set by func %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
947 if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointerEXT) ||
948 (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointerEXT) ||
949 (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointerEXT))
953 else if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointerEXT))
957 else if ((size < 1) && (size > 4))
959 process_entrypoint_error("%s: Size of client side array set by func %s must be between 1 and 4\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
964 stride = type_size * size;
966 uint first_vertex_ofs = (start + basevertex) * stride;
967 uint last_vertex_ofs = (end + basevertex) * stride;
968 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
969 uint total_data_size = last_vertex_ofs + stride;
974 process_entrypoint_error("%s: Failed finding client side vertex data blob set by func %s \n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
980 if (vertex_data_size != pVertex_blob->size())
982 process_entrypoint_error("%s: %s will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, vertex_data_size, pVertex_blob->size());
983 temp_blob = *pVertex_blob;
984 temp_blob.resize(vertex_data_size);
985 pVertex_blob = &temp_blob;
988 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
989 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
990 if (bytes_to_copy != pVertex_blob->size())
992 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
993 process_entrypoint_error("%s: %s accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, first_vertex_ofs + total_data_size);
996 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= array_data.size());
998 memcpy(array_data.get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1002 GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
1007 //----------------------------------------------------------------------------------------------------------------------
1008 // vogl_replayer::set_client_side_vertex_attrib_array_data
1009 // glVertexAttrib client side data
1010 //----------------------------------------------------------------------------------------------------------------------
1011 bool vogl_gl_replayer::set_client_side_vertex_attrib_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
1015 // TODO: Add early out
1017 for (int vertex_attrib_index = 0; vertex_attrib_index < static_cast<int>(m_pCur_context_state->m_context_info.get_max_vertex_attribs()); vertex_attrib_index++)
1019 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(vertex_attrib_index));
1021 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
1026 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1031 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &cur_buf);
1035 GLvoid *attrib_ptr = NULL;
1036 GL_ENTRYPOINT(glGetVertexAttribPointerv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib_ptr);
1040 if (attrib_ptr != m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr())
1046 GLint attrib_size = 0;
1047 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib_size);
1049 GLint attrib_type = 0;
1050 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib_type);
1052 GLint attrib_stride = 0;
1053 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib_stride);
1058 process_entrypoint_error("%s: Failed finding client side vertex data blob for generic vertex attrib %u\n", VOGL_METHOD_NAME, vertex_attrib_index);
1064 if ((attrib_size != GL_BGRA) && (attrib_size < 1) && (attrib_size > 4))
1066 process_entrypoint_error("%s: Enabled vertex attribute index %i has invalid size 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_size);
1069 if ((attrib_size >= 1) && (attrib_size <= 4))
1070 num_comps = attrib_size;
1072 uint type_size = vogl_get_gl_type_size(attrib_type);
1075 process_entrypoint_error("%s: Vertex attribute index %i has unsupported type 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_type);
1079 uint stride = attrib_stride ? attrib_stride : (type_size * num_comps);
1081 uint first_vertex_ofs = (start + basevertex) * stride;
1082 uint last_vertex_ofs = (end + basevertex) * stride;
1083 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
1084 uint total_data_size = last_vertex_ofs + stride;
1086 uint8_vec temp_blob;
1087 if (vertex_data_size != pVertex_blob->size())
1089 process_entrypoint_error("%s: Vertex attribute index %i will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, vertex_attrib_index, vertex_data_size, pVertex_blob->size());
1090 temp_blob = *pVertex_blob;
1091 temp_blob.resize(vertex_data_size);
1092 pVertex_blob = &temp_blob;
1095 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
1096 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
1097 if (bytes_to_copy != pVertex_blob->size())
1099 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
1100 process_entrypoint_error("%s: Vertex attribute index %i accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, vertex_attrib_index, first_vertex_ofs + total_data_size);
1103 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= m_client_side_vertex_attrib_data[vertex_attrib_index].size());
1105 memcpy(m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1111 //----------------------------------------------------------------------------------------------------------------------
1112 // vogl_replayer::draw_elements_client_side_array_setup
1113 //----------------------------------------------------------------------------------------------------------------------
1114 bool vogl_gl_replayer::draw_elements_client_side_array_setup(
1120 vogl_trace_ptr_value trace_indices_ptr_value, const GLvoid *&pIndices,
1122 bool has_valid_start_end,
1127 VOGL_NOTE_UNUSED(mode);
1131 GLuint element_array_buffer = 0;
1132 uint index_size = 0;
1135 index_size = vogl_get_gl_type_size(type);
1138 process_entrypoint_error("%s: Invalid type parameter 0x%08X\n", VOGL_METHOD_NAME, type);
1142 element_array_buffer = vogl_get_bound_gl_buffer(GL_ELEMENT_ARRAY_BUFFER);
1143 if (element_array_buffer)
1145 // trace_indices_ptr_value is actually an offset into the buffer, not a real trace ptr
1146 pIndices = reinterpret_cast<GLvoid *>(trace_indices_ptr_value);
1152 process_entrypoint_warning("%s: count parameter is <= 0 (%i)\n", VOGL_METHOD_NAME, count);
1156 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
1159 if ((indexed) && (!element_array_buffer) && (trace_indices_ptr_value))
1161 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob. Can't remap indices pointer!\n", VOGL_METHOD_NAME);
1162 if (trace_indices_ptr_value)
1164 // We can't remap the pointer to valid memory, so give up.
1169 // TODO: Check for client side array usage but no data in blob (which would be a desync or error)
1173 // TODO: If a VAO is bound, client side data isn't supported according to this:
1174 // http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
1176 //GLint current_vertex_array_binding = 0;
1177 //ACTUAL_GL_ENTRYPOINT(glGetIntegerv)(GL_VERTEX_ARRAY_BINDING, ¤t_vertex_array_binding);
1179 if ((indexed) && (!element_array_buffer))
1181 const uint8_vec *pIndices_vec = map.get_blob(string_hash("indices"));
1184 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob\n", VOGL_METHOD_NAME);
1188 pIndices = pIndices_vec->get_ptr();
1191 process_entrypoint_error("%s: No element array buffer is bound, but key value map has an empty indices blob\n", VOGL_METHOD_NAME);
1195 if ((pIndices_vec->size() / index_size) != static_cast<uint>(count))
1197 process_entrypoint_error("%s: Client side index data blob stored in packet is too small (wanted %u indices, got %u indices)\n", VOGL_METHOD_NAME, count, pIndices_vec->size() / index_size);
1202 if ((indexed) && (!has_valid_start_end))
1204 uint total_index_data_size = count * index_size;
1206 const uint8 *pIndices_to_scan = static_cast<const uint8 *>(pIndices);
1208 if (element_array_buffer)
1210 if (m_index_data.size() < total_index_data_size)
1211 m_index_data.resize(total_index_data_size);
1213 pIndices_to_scan = m_index_data.get_ptr();
1217 GL_ENTRYPOINT(glGetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)pIndices, total_index_data_size, m_index_data.get_ptr());
1219 if (check_gl_error())
1221 process_entrypoint_warning("%s: GL error while trying to retrieve index buffer data\n", VOGL_METHOD_NAME);
1223 memset(m_index_data.get_ptr(), 0, total_index_data_size);
1227 start = cUINT32_MAX;
1230 for (int i = 0; i < count; i++)
1234 if (type == GL_UNSIGNED_BYTE)
1235 v = pIndices_to_scan[i];
1236 else if (type == GL_UNSIGNED_SHORT)
1237 v = reinterpret_cast<const uint16 *>(pIndices_to_scan)[i];
1238 else if (type == GL_UNSIGNED_INT)
1239 v = reinterpret_cast<const uint32 *>(pIndices_to_scan)[i];
1242 process_entrypoint_error("%s: Invalid index type\n", VOGL_METHOD_NAME);
1246 start = math::minimum(start, v);
1247 end = math::maximum(end, v);
1250 has_valid_start_end = true;
1253 if (!set_client_side_array_data(map, start, end, basevertex))
1256 if (!set_client_side_vertex_attrib_array_data(map, start, end, basevertex))
1262 //----------------------------------------------------------------------------------------------------------------------
1263 // vogl_replayer::determine_uniform_replay_location
1264 //----------------------------------------------------------------------------------------------------------------------
1265 GLint vogl_gl_replayer::determine_uniform_replay_location(GLuint trace_program, GLint trace_location)
1269 // Seems better to return -1 when we can't find the uniform (which can happen if the driver optimizes the program differently vs. tracing).
1270 // Otherwise, we can pass an invalid handle down to the driver and this will crash AMD's fglrx.
1271 //GLint replay_location = trace_location;
1272 GLint replay_location = -1;
1274 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1275 if (it == get_shared_state()->m_glsl_program_hash_map.end())
1277 process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1281 glsl_program_state &state = it->second;
1283 uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1284 if (loc_it == state.m_uniform_locations.end())
1286 process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1290 replay_location = loc_it->second;
1293 return replay_location;
1296 //----------------------------------------------------------------------------------------------------------------------
1297 // vogl_replayer::process_entrypoint_print_summary_context
1298 //----------------------------------------------------------------------------------------------------------------------
1299 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1303 if (!m_pCur_gl_packet)
1306 console::printf(msg_type, "While processing GL entrypoint packet func %s, frame %u, swaps %u, GL call counter %" PRIu64 ", packet start trace context 0x%" PRIX64 ", cur trace context 0x%" PRIX64 ", trace thread 0x%" PRIX64 ":\n",
1307 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1308 m_frame_index, m_total_swaps,
1309 m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1310 m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1311 m_cur_trace_context,
1312 m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1315 dynamic_string_array backtrace;
1316 if (get_printable_backtrace(backtrace))
1318 console::printf("Backtrace:\n");
1319 for (uint i = 0; i < backtrace.size(); i++)
1320 console::printf("%s\n", backtrace[i].get_ptr());
1325 //----------------------------------------------------------------------------------------------------------------------
1326 // vogl_replayer::print_detailed_context
1327 //----------------------------------------------------------------------------------------------------------------------
1328 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1334 vogl_loose_file_blob_manager blob_file_manager;
1335 blob_file_manager.init(cBMFWritable);
1337 vogl_trace_packet::json_serialize_params serialize_params;
1338 serialize_params.m_output_basename = "replay_error";
1339 serialize_params.m_cur_frame = m_frame_index;
1340 serialize_params.m_blob_file_size_threshold = 1024;
1341 serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1342 m_pCur_gl_packet->json_serialize(node, serialize_params);
1344 dynamic_string node_str;
1345 node.serialize(node_str, true, 0);
1346 console::printf(msg_type, "Packet at call counter %" PRIu64 " as JSON:\n%s\n", m_pCur_gl_packet->get_entrypoint_packet().m_call_counter, node_str.get_ptr());
1349 //----------------------------------------------------------------------------------------------------------------------
1350 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1351 //----------------------------------------------------------------------------------------------------------------------
1352 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1356 if (!m_pCur_gl_packet)
1359 dump_packet_as_func_call(*m_pCur_gl_packet);
1361 if (!(m_flags & cGLReplayerDumpPacketsOnError))
1364 print_detailed_context(msg_type);
1367 //----------------------------------------------------------------------------------------------------------------------
1368 // vogl_replayer::process_entrypoint_info
1369 //----------------------------------------------------------------------------------------------------------------------
1370 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1374 process_entrypoint_print_summary_context(cInfoConsoleMessage);
1377 va_start(args, pFmt);
1378 console::vprintf(cInfoConsoleMessage, pFmt, args);
1381 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1384 //----------------------------------------------------------------------------------------------------------------------
1385 // vogl_replayer::process_entrypoint_message
1386 //----------------------------------------------------------------------------------------------------------------------
1387 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1391 process_entrypoint_print_summary_context(cMessageConsoleMessage);
1394 va_start(args, pFmt);
1395 console::vprintf(cMessageConsoleMessage, pFmt, args);
1398 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1401 //----------------------------------------------------------------------------------------------------------------------
1402 // vogl_replayer::process_entrypoint_warning
1403 //----------------------------------------------------------------------------------------------------------------------
1404 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1408 process_entrypoint_print_summary_context(cWarningConsoleMessage);
1411 va_start(args, pFmt);
1412 console::vprintf(cWarningConsoleMessage, pFmt, args);
1415 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1418 //----------------------------------------------------------------------------------------------------------------------
1419 // vogl_replayer::process_entrypoint_error
1420 //----------------------------------------------------------------------------------------------------------------------
1421 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1425 process_entrypoint_print_summary_context(cErrorConsoleMessage);
1428 va_start(args, pFmt);
1429 console::vprintf(cErrorConsoleMessage, pFmt, args);
1432 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1435 //----------------------------------------------------------------------------------------------------------------------
1436 // vogl_replayer::switch_contexts
1437 //----------------------------------------------------------------------------------------------------------------------
1438 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1443 //if (m_pCur_gl_packet->get_call_counter() == 25583)
1444 // vogl_debug_break();
1446 //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1447 if (trace_context == m_cur_trace_context)
1450 if (m_flags & cGLReplayerDebugMode)
1452 process_entrypoint_message("%s: Forcing context switch via glXMakeCurrent, from current trace context 0x%" PRIX64 " to new context 0x%" PRIX64 "\n", VOGL_METHOD_NAME, cast_val_to_uint64(m_cur_trace_context), cast_val_to_uint64(trace_context));
1455 // pContext_state will be NULL if they are unmapping!
1456 context_state *pContext_state = get_trace_context_state(trace_context);
1457 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1459 const Display *dpy = m_pWindow->get_display();
1460 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1462 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1465 process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1466 return cStatusHardFailure;
1469 m_cur_trace_context = trace_context;
1470 m_cur_replay_context = replay_context;
1471 m_pCur_context_state = pContext_state;
1476 //----------------------------------------------------------------------------------------------------------------------
1477 // vogl_replayer::debug_callback_arb
1478 //----------------------------------------------------------------------------------------------------------------------
1479 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1483 VOGL_NOTE_UNUSED(length);
1485 char final_message[4096];
1487 context_state *pContext_state = (context_state *)(pUser_param);
1489 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1493 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1494 cast_val_to_uint64(pContext_state->m_trace_context), cast_val_to_uint64(pContext_state->m_replay_context), cast_val_to_uint64(pContext_state->m_last_call_counter), final_message);
1498 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1502 //----------------------------------------------------------------------------------------------------------------------
1503 // vogl_replayer::debug_callback
1504 //----------------------------------------------------------------------------------------------------------------------
1505 void vogl_gl_replayer::debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1509 VOGL_NOTE_UNUSED(length);
1511 char final_message[4096];
1513 context_state *pContext_state = (context_state *)(pUser_param);
1515 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1519 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1520 cast_val_to_uint64(pContext_state->m_trace_context), cast_val_to_uint64(pContext_state->m_replay_context), cast_val_to_uint64(pContext_state->m_last_call_counter), final_message);
1524 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1528 //----------------------------------------------------------------------------------------------------------------------
1529 // vogl_replayer::is_extension_supported
1530 //----------------------------------------------------------------------------------------------------------------------
1531 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1535 if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1537 return m_pCur_context_state->m_context_info.supports_extension(pExt);
1545 //----------------------------------------------------------------------------------------------------------------------
1546 // vogl_replayer::context_state::handle_context_made_current
1547 //----------------------------------------------------------------------------------------------------------------------
1548 bool vogl_gl_replayer::context_state::handle_context_made_current()
1552 if (m_has_been_made_current)
1555 VOGL_CHECK_GL_ERROR;
1557 m_has_been_made_current = true;
1559 if (!m_context_info.init(m_context_desc))
1561 vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1565 if (!m_context_info.get_max_vertex_attribs())
1567 vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1569 else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1571 vogl_error_printf("%s: GL_MAX_VERTEX_ATTRIBS is too large, max supported is %u. Please increase VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES.\n", VOGL_METHOD_NAME, VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES);
1575 if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1577 vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1580 // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1581 // TODO: All more object types
1582 vogl::vector<GLuint> dummy_handles(65536);
1584 GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1585 GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1586 GL_ENTRYPOINT(glGenLists)(8000);
1587 GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1589 GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1590 GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1591 GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1592 GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1593 GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1595 for (uint i = 0; i < 22000; i++)
1596 GL_ENTRYPOINT(glCreateProgram)();
1598 vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1601 VOGL_CHECK_GL_ERROR;
1606 //----------------------------------------------------------------------------------------------------------------------
1607 // vogl_replayer::handle_context_made_current
1608 //----------------------------------------------------------------------------------------------------------------------
1609 bool vogl_gl_replayer::handle_context_made_current()
1613 if (!m_pCur_context_state->handle_context_made_current())
1616 if ((m_pCur_context_state->m_context_info.is_debug_context()) && (GL_ENTRYPOINT(glDebugMessageCallbackARB)) && (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_debug_output")))
1618 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1619 GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1623 if (m_flags & cGLReplayerVerboseMode)
1625 vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1627 (uint64_t)m_cur_trace_context,
1628 (uint64_t)m_cur_replay_context,
1629 m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1635 //----------------------------------------------------------------------------------------------------------------------
1636 // vogl_replayer::dump_context_attrib_list
1637 //----------------------------------------------------------------------------------------------------------------------
1638 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1644 vogl_debug_printf("Attrib list is NULL\n");
1647 vogl_debug_printf("Context attribs:\n");
1654 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1658 uint key = pAttrib_list[ofs];
1665 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1669 uint value = pAttrib_list[ofs];
1672 vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1674 vogl_debug_printf("End of context attribs\n");
1677 //----------------------------------------------------------------------------------------------------------------------
1678 // vogl_replayer::find_attrib_key
1679 //----------------------------------------------------------------------------------------------------------------------
1680 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1685 while (ofs < attrib_list.size())
1687 int key = attrib_list[ofs];
1691 if (++ofs >= attrib_list.size())
1693 process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1697 if (key == key_to_find)
1705 //----------------------------------------------------------------------------------------------------------------------
1706 // vogl_replayer::create_context_attribs
1707 //----------------------------------------------------------------------------------------------------------------------
1708 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1709 vogl_trace_context_ptr_value trace_context, Display *dpy, GLXFBConfig config, vogl_trace_context_ptr_value trace_share_context, GLXContext replay_share_context, Bool direct,
1710 const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1714 vogl::vector<int> temp_attrib_list;
1716 if ((pTrace_attrib_list) && (trace_attrib_list_size))
1718 temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1719 if (temp_attrib_list.back() != 0)
1721 process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1726 if (expecting_attribs)
1728 if (m_flags & cGLReplayerVerboseMode)
1729 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1732 temp_attrib_list.push_back(0);
1735 if (m_flags & cGLReplayerForceDebugContexts)
1737 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1738 int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1739 if (context_flags_ofs < 0)
1741 temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1742 temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1743 temp_attrib_list.push_back(0);
1745 if (m_flags & cGLReplayerVerboseMode)
1746 process_entrypoint_warning("%s: Appending GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB to attrib list to enable debug context\n", VOGL_METHOD_NAME);
1750 temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1752 if (m_flags & cGLReplayerVerboseMode)
1753 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1756 int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1757 int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1759 bool slammed_up_to_3_0 = false;
1760 if (context_major_version_ofs < 0)
1762 // Don't slam up if they haven't requested a specific GL version, the driver will give us the most recent version that is backwards compatible with 1.0 (i.e. 4.3 for NVidia's current dirver).
1764 temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1765 temp_attrib_list.push_back(3);
1766 temp_attrib_list.push_back(0);
1768 slammed_up_to_3_0 = true;
1771 else if (temp_attrib_list[context_major_version_ofs] < 3)
1773 temp_attrib_list[context_major_version_ofs] = 3;
1775 slammed_up_to_3_0 = true;
1778 if (slammed_up_to_3_0)
1780 if (context_minor_version_ofs < 0)
1782 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1783 temp_attrib_list.push_back(0);
1784 temp_attrib_list.push_back(0);
1788 temp_attrib_list[context_minor_version_ofs] = 0;
1791 process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1795 const int *pAttrib_list = temp_attrib_list.get_ptr();
1796 const uint attrib_list_size = temp_attrib_list.size();
1798 if (m_flags & cGLReplayerVerboseMode)
1799 dump_context_attrib_list(pAttrib_list, attrib_list_size);
1801 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1802 if (!replay_context)
1806 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1807 return cStatusHardFailure;
1811 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1819 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1820 VOGL_NOTE_UNUSED(pContext_state);
1824 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1831 //----------------------------------------------------------------------------------------------------------------------
1832 // vogl_replayer::process_pending_make_current
1833 //----------------------------------------------------------------------------------------------------------------------
1834 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1838 if (!m_pending_make_current_packet.is_valid())
1841 vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1843 Bool trace_result = gl_packet.get_return_value<Bool>();
1845 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1846 VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1848 // pContext_state will be NULL if they are unmapping!
1849 vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1850 context_state *pContext_state = get_trace_context_state(trace_context);
1851 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1853 if ((trace_context) && (!replay_context))
1855 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1856 m_pending_make_current_packet.clear();
1857 return cStatusHardFailure;
1860 const Display *dpy = m_pWindow->get_display();
1861 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1863 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1868 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1869 m_pending_make_current_packet.clear();
1870 return cStatusHardFailure;
1874 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1879 m_cur_trace_context = trace_context;
1880 m_cur_replay_context = replay_context;
1881 m_pCur_context_state = pContext_state;
1885 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1888 if (m_cur_replay_context)
1890 int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1891 int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1892 int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1893 int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1894 int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1895 int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1897 if (!m_pCur_context_state->m_has_been_made_current)
1899 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1900 viewport_x, viewport_y,
1901 viewport_width, viewport_height,
1902 win_width, win_height);
1905 GLint cur_viewport[4];
1906 GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1908 uint cur_win_width = 0, cur_win_height = 0;
1909 m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1911 if (!m_pCur_context_state->m_has_been_made_current)
1913 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1914 cur_viewport[0], cur_viewport[1],
1915 cur_viewport[2], cur_viewport[3],
1916 cur_win_width, cur_win_height);
1919 if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1921 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1924 if (!handle_context_made_current())
1925 return cStatusHardFailure;
1929 m_last_processed_call_counter = gl_packet.get_call_counter();
1931 m_pending_make_current_packet.clear();
1936 //----------------------------------------------------------------------------------------------------------------------
1937 // vogl_process_internal_trace_command_ctypes_packet
1938 //----------------------------------------------------------------------------------------------------------------------
1939 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1943 // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1944 int num_trace_ctypes = kvm.get_int("num_ctypes");
1945 VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1947 // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1948 // This will need to be revisited once we port to other OS's.
1949 // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1950 for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1952 const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1954 uint base_index = ctype_iter << 8;
1955 dynamic_string name(kvm.get_string(base_index++));
1956 dynamic_string ctype(kvm.get_string(base_index++));
1957 int size = kvm.get_int(base_index++);
1958 uint loki_type_flags = kvm.get_uint(base_index++);
1959 bool is_pointer = kvm.get_bool(base_index++);
1960 bool is_opaque_pointer = kvm.get_bool(base_index++);
1961 bool is_pointer_diff = kvm.get_bool(base_index++);
1962 bool is_opaque_type = kvm.get_bool(base_index++);
1964 VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1965 VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1966 if (!desc.m_is_opaque_type)
1968 VOGL_VERIFY(size == desc.m_size);
1971 const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1972 VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1974 VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1975 VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1976 VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1977 VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1983 //----------------------------------------------------------------------------------------------------------------------
1984 // vogl_replayer::process_internal_trace_command
1985 //----------------------------------------------------------------------------------------------------------------------
1986 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1990 VOGL_NOTE_UNUSED(gl_packet);
1992 GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1993 GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1994 VOGL_NOTE_UNUSED(size);
1995 vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1996 VOGL_NOTE_UNUSED(trace_data_ptr_value);
1998 vogl_gl_replayer::status_t status = cStatusOK;
2002 case cITCRDemarcation:
2006 case cITCRKeyValueMap:
2008 const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
2010 dynamic_string cmd_type(kvm.get_string("command_type"));
2011 if (cmd_type == "state_snapshot")
2013 dynamic_string text_id(kvm.get_string("id"));
2014 dynamic_string binary_id(kvm.get_string("binary_id"));
2015 if (text_id.is_empty() && binary_id.is_empty())
2017 process_entrypoint_error("%s: Missing id and binary_id fields in glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2018 return cStatusHardFailure;
2021 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
2023 // TODO: Make a 1st class snapshot cache class
2024 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
2025 vogl_gl_state_snapshot *pSnapshot = NULL;
2026 if (m_flags & cGLReplayerSnapshotCaching)
2028 for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
2030 if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
2032 pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
2035 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2036 m_snapshots.erase(snapshot_index);
2037 m_snapshots.insert(0, cache_entry);
2046 timed_scope ts("Deserialize snapshot time");
2048 if (!m_pBlob_manager)
2050 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2051 return cStatusHardFailure;
2054 uint8_vec snapshot_data;
2056 if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2058 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2059 return cStatusHardFailure;
2062 vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2067 if (id_to_use == text_id)
2068 success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2070 success = doc.binary_deserialize(snapshot_data);
2071 if (!success || (!doc.get_root()))
2073 process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2074 return cStatusHardFailure;
2077 pSnapshot = vogl_new(vogl_gl_state_snapshot);
2078 if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2080 vogl_delete(pSnapshot);
2083 process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2084 return cStatusHardFailure;
2087 if (m_flags & cGLReplayerSnapshotCaching)
2089 snapshot_cache_entry new_cache_entry;
2090 new_cache_entry.m_name = id_to_use;
2091 new_cache_entry.m_pSnapshot = pSnapshot;
2092 m_snapshots.insert(0, new_cache_entry);
2094 // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2095 while (m_snapshots.size() > 3)
2097 vogl_delete(m_snapshots.back().m_pSnapshot);
2098 m_snapshots.resize(m_snapshots.size() - 1);
2103 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2105 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2107 if (m_flags & cGLReplayerSnapshotCaching)
2109 VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2111 vogl_delete(m_snapshots[0].m_pSnapshot);
2112 m_snapshots.erase(0U);
2115 if (m_flags & cGLReplayerSnapshotCaching)
2117 vogl_delete(pSnapshot);
2121 process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2125 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2127 else if (cmd_type == "ctypes")
2129 m_ctypes_packet = *m_pCur_gl_packet;
2131 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2132 return cStatusHardFailure;
2134 else if (cmd_type == "entrypoints")
2140 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2146 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2154 //----------------------------------------------------------------------------------------------------------------------
2155 // vogl_replayer::check_program_binding_shadow
2156 //----------------------------------------------------------------------------------------------------------------------
2157 bool vogl_gl_replayer::check_program_binding_shadow()
2161 if (!m_pCur_context_state)
2164 // Make sure shadow is good
2165 GLint actual_current_replay_program = 0;
2166 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2169 if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2172 // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2173 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2174 if ((!check_gl_error()) && (is_still_program))
2176 GLint marked_for_deletion = GL_FALSE;
2177 GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2179 if ((!check_gl_error()) && (marked_for_deletion))
2187 //----------------------------------------------------------------------------------------------------------------------
2188 // vogl_replayer::handle_use_program
2189 //----------------------------------------------------------------------------------------------------------------------
2190 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2194 // TODO: This code assumes the non-ARB entrypoints are being used, which works fine on NV but who knows what'll happen on other drivers.
2195 check_program_binding_shadow();
2197 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2198 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2199 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2201 // For safety, absorb any previous error.
2204 GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2205 GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2207 bool prev_is_program = false;
2208 GLint prev_link_status = false;
2209 GLint prev_is_marked_for_deletion = false;
2210 vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2212 if ((prev_replay_program) && (replay_handle != prev_replay_program))
2214 prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2215 check_gl_error_quietly();
2217 if (prev_is_program)
2219 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2220 check_gl_error_quietly();
2222 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2223 check_gl_error_quietly();
2225 if (prev_is_marked_for_deletion)
2227 // The currently bound program is marked for deletion, so record which shaders are attached to it in case the program is actually deleted by the driver on the UseProgram() call.
2228 GLint num_attached_shaders = 0;
2229 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2230 check_gl_error_quietly();
2232 if (num_attached_shaders)
2234 prev_attached_replay_shaders.resize(num_attached_shaders);
2236 GLsizei actual_count = 0;
2237 GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2238 check_gl_error_quietly();
2240 VOGL_ASSERT(actual_count == num_attached_shaders);
2246 if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2247 GL_ENTRYPOINT(glUseProgram)(replay_handle);
2249 GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2251 // Can't shadow if glUseProgram failed.
2252 if (check_gl_error())
2255 if ((prev_replay_program) && (prev_replay_program != replay_handle))
2257 bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2258 if (!is_prev_still_program)
2260 VOGL_ASSERT(prev_is_program);
2261 VOGL_ASSERT(prev_is_marked_for_deletion);
2263 // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2264 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2265 VOGL_ASSERT(was_deleted);
2266 VOGL_NOTE_UNUSED(was_deleted);
2268 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2269 VOGL_ASSERT(was_deleted);
2271 was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2272 if ((prev_link_status) && (!was_deleted))
2277 for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2279 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2281 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2282 check_gl_error_quietly();
2284 if (is_still_shader)
2287 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2289 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2293 // The attached shader is now really dead.
2294 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2295 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2297 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, prev_trace_program, prev_replay_program);
2303 m_pCur_context_state->m_cur_replay_program = replay_handle;
2304 m_pCur_context_state->m_cur_trace_program = trace_handle;
2307 //----------------------------------------------------------------------------------------------------------------------
2308 // vogl_replayer::handle_delete_program
2309 //----------------------------------------------------------------------------------------------------------------------
2310 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2314 check_program_binding_shadow();
2316 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2318 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2319 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2320 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2322 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2323 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2325 if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2328 context_state *pContext = it->second;
2329 if (pContext->m_pShared_state == pContext_shareroot)
2331 if (pContext->m_cur_trace_program == trace_handle)
2333 process_entrypoint_error("%s: Trace program %u replay program %u is being deleted on context 0x%" PRIx64 ", but it's currently bound to trace context 0x%" PRIx64 "! This scenario is not currently supported with sharelists.\n",
2334 VOGL_METHOD_NAME, trace_handle, replay_handle,
2335 cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2336 cast_val_to_uint64(it->first));
2341 bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2342 check_gl_error_quietly();
2344 vogl::growable_array<GLuint, 8> attached_replay_shaders;
2346 if ((is_program) && (replay_handle))
2348 GLint num_attached_shaders = 0;
2349 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2350 check_gl_error_quietly();
2352 if (num_attached_shaders)
2354 attached_replay_shaders.resize(num_attached_shaders);
2356 GLsizei actual_count = 0;
2357 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2358 check_gl_error_quietly();
2360 VOGL_ASSERT(actual_count == num_attached_shaders);
2364 GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2366 bool deletion_succeeded = !check_gl_error();
2367 if (!deletion_succeeded)
2369 VOGL_ASSERT(!is_program);
2371 process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2378 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2379 check_gl_error_quietly();
2381 GLint marked_for_deletion = 0;
2382 if (is_still_program)
2384 // It must still be bound to the context, or referred to in some other way that we don't know about.
2385 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2386 bool delete_status_check_succeeded = !check_gl_error_quietly();
2388 VOGL_VERIFY(delete_status_check_succeeded);
2389 VOGL_VERIFY(marked_for_deletion);
2391 else if (!is_still_program)
2393 VOGL_ASSERT(is_program);
2395 // The program is really gone now.
2396 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2397 VOGL_ASSERT(was_deleted);
2398 VOGL_NOTE_UNUSED(was_deleted);
2400 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2401 VOGL_ASSERT(was_deleted);
2403 get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2405 if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2407 // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2409 m_pCur_context_state->m_cur_replay_program = 0;
2410 m_pCur_context_state->m_cur_trace_program = 0;
2413 for (uint i = 0; i < attached_replay_shaders.size(); i++)
2415 GLuint replay_shader_handle = attached_replay_shaders[i];
2417 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2418 check_gl_error_quietly();
2420 if (is_still_shader)
2423 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2425 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2429 // The attached shader is now really dead.
2430 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2431 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2433 process_entrypoint_error("%s: Failed finding attached GL shader %u in objects hash table, while handling the actual deletion of trace program %u replay program %u\n", VOGL_METHOD_NAME, replay_shader_handle, trace_handle, replay_handle);
2439 //----------------------------------------------------------------------------------------------------------------------
2440 // vogl_replayer::handle_delete_shader
2441 //----------------------------------------------------------------------------------------------------------------------
2442 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2446 check_program_binding_shadow();
2450 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2452 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2453 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2454 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2456 GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2458 bool deletion_succeeded = !check_gl_error();
2459 if (!deletion_succeeded)
2461 process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2468 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2469 check_gl_error_quietly();
2471 if (!is_still_shader)
2473 // The shader is really gone.
2474 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2475 VOGL_ASSERT(was_deleted);
2476 VOGL_NOTE_UNUSED(was_deleted);
2480 GLint marked_for_deletion = 0;
2481 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2482 check_gl_error_quietly();
2484 VOGL_VERIFY(marked_for_deletion);
2486 // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2487 // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2491 //----------------------------------------------------------------------------------------------------------------------
2492 // vogl_replayer::handle_detach_shader
2493 //----------------------------------------------------------------------------------------------------------------------
2494 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2496 GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2497 GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2499 GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2500 GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2504 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2506 GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2507 check_gl_error_quietly();
2509 GLint marked_for_deletion = 0;
2510 GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2511 check_gl_error_quietly();
2513 if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2514 GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2517 VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2518 GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2521 bool detach_failed = check_gl_error();
2523 GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2524 check_gl_error_quietly();
2528 if ((marked_for_deletion) && (was_shader) && (!is_shader))
2530 // The shader is really gone now.
2531 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2532 VOGL_ASSERT(was_deleted);
2533 VOGL_NOTE_UNUSED(was_deleted);
2538 //----------------------------------------------------------------------------------------------------------------------
2539 // vogl_gl_replayer::handle_link_program
2540 //----------------------------------------------------------------------------------------------------------------------
2541 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2545 GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2546 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2548 GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2552 process_entrypoint_warning("%s: Handle is not a program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2555 const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2559 process_entrypoint_warning("%s: JSON metadata document is missing, program will be linked without setting its attributes or initializing the uniform location shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2561 else if ((pDoc) && (!pDoc->is_object()))
2563 process_entrypoint_warning("%s: JSON metadata document must be an object, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2567 int trace_active_attributes = 0;
2568 int trace_active_uniforms = 0;
2569 int trace_active_uniform_blocks = 0;
2570 int trace_link_status = 1;
2572 VOGL_NOTE_UNUSED(trace_active_uniforms);
2573 VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2577 const json_node &doc_root = *pDoc->get_root();
2579 trace_link_status = doc_root.value_as_int("link_status");
2580 trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2581 trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2582 trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2584 const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2587 for (uint i = 0; i < pAttrib_node->size(); i++)
2589 const json_node *pAttrib = pAttrib_node->get_child(i);
2596 const char *pName = pAttrib->value_as_string_ptr("name");
2597 int attrib_loc = pAttrib->value_as_int("location", -1);
2599 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2601 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2602 GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2604 GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2611 const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2612 if (pOutputs_object)
2614 for (uint i = 0; i < pOutputs_object->size(); i++)
2616 const json_node *pOutput_node = pOutputs_object->get_child(i);
2620 dynamic_string name(pOutput_node->value_as_string("name"));
2621 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2624 int location = pOutput_node->value_as_int("location");
2625 int location_index = pOutput_node->value_as_int("location_index");
2627 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2629 GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2634 process_entrypoint_error("%s: GL_ARB_blend_func_extended is not supported, but trace program %u GL program %u uses a non-zero location index\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2636 GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2643 GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2644 GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2647 const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2648 if (pTransform_feedback_varyings)
2650 dynamic_string_array names;
2652 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2654 const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2658 GLint index = pVarying_node->value_as_int("index");
2662 dynamic_string name(pVarying_node->value_as_string("name"));
2664 //GLsizei size(pVarying_node->value_as_int("size"));
2665 //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2667 names.ensure_element_is_valid(index);
2668 names[index] = name;
2671 vogl::vector<GLchar *> varyings(names.size());
2672 for (uint i = 0; i < names.size(); i++)
2673 varyings[i] = (GLchar *)(names[i].get_ptr());
2675 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2681 switch (entrypoint_id)
2683 case VOGL_ENTRYPOINT_glLinkProgram:
2685 GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2688 case VOGL_ENTRYPOINT_glLinkProgramARB:
2690 GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2693 case VOGL_ENTRYPOINT_glProgramBinary:
2695 GL_ENTRYPOINT(glProgramBinary)(replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2707 GLint replay_link_status = 0;
2708 GLint replay_active_attributes = 0;
2709 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2711 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2714 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2719 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2722 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2726 if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2729 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2730 success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle, m_pCur_gl_packet->get_param_value<GLenum>(1), m_pCur_gl_packet->get_param_client_memory<GLvoid>(2), m_pCur_gl_packet->get_param_value<GLsizei>(3));
2732 success = get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, replay_handle);
2735 process_entrypoint_warning("%s: Failed inserting into link time program shadow, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2738 if ((pDoc) && (replay_link_status != trace_link_status))
2740 process_entrypoint_warning("%s: Trace link status (%i) differs from replay link status (%i), trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_link_status, replay_link_status, trace_handle, replay_handle);
2743 if (!replay_link_status)
2745 vogl::vector<GLchar> log;
2747 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2750 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2757 GLint actual_length = 0;
2758 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2765 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2772 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2777 if ((log.size()) && (log[0]))
2779 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
2783 if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2785 process_entrypoint_warning("%s: Number of trace active attributes (%i) differs from number of replay active attributes (%i) after linking program, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, trace_active_attributes, replay_active_attributes, trace_handle, replay_handle);
2788 const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2792 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2793 if (it == get_shared_state()->m_glsl_program_hash_map.end())
2794 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2795 glsl_program_state &prog_state = it->second;
2797 for (uint i = 0; i < pUniforms_node->size(); i++)
2799 const json_node *pUniform = pUniforms_node->get_child(i);
2806 const char *pName = pUniform->value_as_string_ptr("name");
2812 int trace_loc = pUniform->value_as_int("location");
2813 int trace_array_size = pUniform->value_as_int("size");
2814 //int trace_type = pUniform->value_as_int("type");
2816 VOGL_ASSERT(trace_array_size >= 1);
2818 if ((trace_loc < 0) || (trace_array_size <= 0))
2821 if (trace_array_size > 1)
2823 dynamic_string element_name;
2824 for (int i = 0; i < trace_array_size; i++)
2826 element_name = pName;
2827 int start_bracket_ofs = element_name.find_right('[');
2828 if (start_bracket_ofs >= 0)
2829 element_name.left(start_bracket_ofs);
2830 element_name.format_append("[%u]", i);
2832 GLint element_trace_loc = trace_loc + i;
2833 GLint element_replay_loc;
2834 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2835 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2837 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2840 if (element_replay_loc < 0)
2842 process_entrypoint_warning("%s: glGetUniformLocation: Trace active array uniform %s trace location %i trace array size %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, element_name.get_ptr(), trace_loc, trace_array_size, trace_handle, replay_handle);
2846 prog_state.m_uniform_locations.erase(element_trace_loc);
2847 prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2851 else if (trace_array_size == 1)
2854 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2855 replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2857 replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2862 process_entrypoint_warning("%s: glGetUniformLocation: Trace active uniform %s trace location %i is not active during replay, trace program 0x%X replay program 0x%X\n", VOGL_METHOD_NAME, pName, trace_loc, trace_handle, replay_handle);
2866 prog_state.m_uniform_locations.erase(trace_loc);
2867 prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2874 //----------------------------------------------------------------------------------------------------------------------
2875 // vogl_gl_replayer::post_draw_call
2876 // Called after each draw call or blit.
2877 //----------------------------------------------------------------------------------------------------------------------
2878 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2882 if (m_pCur_context_state->m_inside_gl_begin)
2885 if (check_gl_error())
2886 return cStatusGLError;
2888 bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2890 if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2892 dump_current_shaders();
2895 if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2897 bool should_dump = false;
2899 if (m_dump_framebuffer_on_draw_frame_index != -1)
2901 if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2904 else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2906 should_dump = math::is_within_closed_range<uint64_t>(m_last_parsed_call_counter, m_dump_framebuffer_on_draw_first_gl_call_index, m_dump_framebuffer_on_draw_last_gl_call_index);
2915 dump_current_framebuffer();
2919 m_frame_draw_counter += is_draw;
2924 //----------------------------------------------------------------------------------------------------------------------
2925 // vogl_gl_replayer::dump_framebuffer
2926 //----------------------------------------------------------------------------------------------------------------------
2927 bool vogl_gl_replayer::dump_framebuffer(uint width, uint height, GLuint read_framebuffer, GLenum read_buffer, GLenum internal_format, uint orig_samples, GLuint replay_texture, GLuint replay_rbo)
2931 uint trace_read_framebuffer = 0;
2932 if (read_framebuffer)
2934 gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2935 if (it != get_context_state()->m_framebuffers.end())
2936 trace_read_framebuffer = it->second;
2939 uint trace_texture = replay_texture;
2942 if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2943 vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2949 if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2950 vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2953 m_screenshot_buffer.resize(width * height * 3);
2955 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, read_framebuffer, read_buffer, 0);
2959 process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2963 size_t png_size = 0;
2964 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2966 dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2967 m_dump_framebuffer_on_draw_prefix.get_ptr(),
2968 (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2969 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2971 (unsigned long long)m_frame_draw_counter,
2973 trace_read_framebuffer,
2974 g_gl_enums.find_gl_name(read_buffer));
2976 if (internal_format != GL_NONE)
2978 screenshot_filename += "_";
2979 screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2982 if (orig_samples != 0)
2983 screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2985 screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2987 screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2989 screenshot_filename += ".png";
2991 file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2993 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2995 process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
3000 vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
3008 //----------------------------------------------------------------------------------------------------------------------
3009 // vogl_gl_replayer::dump_current_framebuffer
3010 //----------------------------------------------------------------------------------------------------------------------
3011 void vogl_gl_replayer::dump_current_framebuffer()
3015 uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
3017 uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
3018 if (!max_draw_buffers)
3020 process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
3024 //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
3026 vogl::vector<GLenum> draw_buffers(max_draw_buffers);
3027 for (uint i = 0; i < max_draw_buffers; i++)
3028 draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
3030 if (!draw_framebuffer_binding)
3032 for (uint i = 0; i < max_draw_buffers; i++)
3033 if (draw_buffers[i] != GL_NONE)
3034 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3038 // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3039 vogl_framebuffer_state fbo_state;
3040 if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3042 process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3046 for (uint i = 0; i < draw_buffers.size(); i++)
3048 if (draw_buffers[i] == GL_NONE)
3051 const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3054 process_entrypoint_warning("%s: Can't find draw buffer %s in currently bound FBO %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(draw_buffers[i]), draw_framebuffer_binding);
3058 if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3060 else if (pAttachment->get_type() == GL_RENDERBUFFER)
3062 GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3066 vogl_renderbuffer_state rbo_state;
3067 if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3069 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3073 if (rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_DEPTH_SIZE) || rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_STENCIL_SIZE))
3076 uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3077 uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3078 uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3079 GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3081 if ((!width) || (!height) || (!internal_format))
3083 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's RBO %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3089 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3091 GLuint temp_rbo = 0;
3092 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3098 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3101 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3104 GLuint temp_fbo = 0;
3105 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3108 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3111 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3114 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3115 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3118 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3121 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3124 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3126 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3129 // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3130 vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3132 GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3135 GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3137 if (!check_gl_error())
3138 dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3141 process_entrypoint_warning("%s: Failed downsampling FBO %u color attachment %u's RBO %u to temporary RBO\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, rbo_handle);
3145 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3148 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3151 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3154 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3159 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3162 else if (pAttachment->get_type() == GL_TEXTURE)
3164 GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3167 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3171 GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3172 if (target == GL_NONE)
3174 process_entrypoint_warning("%s: Current FBO %u first color attachment's type is GL_TEXTURE, but unable to determine the texture's target type, GL texture handle %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding, tex_handle);
3178 if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3179 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3181 if (!utils::is_in_set<GLenum, GLenum>(target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY))
3183 process_entrypoint_warning("%s: Unsupported FBO attachment texture target type (%s), GL texture handle %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(target), tex_handle);
3187 uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3188 uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3189 VOGL_NOTE_UNUSED(layer);
3191 GLint width = 0, height = 0, samples = 0;
3192 GLenum internal_format = GL_NONE;
3195 vogl_scoped_binding_state binding_saver;
3196 binding_saver.save_textures();
3198 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3201 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3204 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3207 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3210 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3212 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3217 if ((!width) || (!height))
3219 process_entrypoint_warning("%s: Unable to determine FBO %u color attachment %u's texture %u's dimensions\n", VOGL_METHOD_NAME, draw_framebuffer_binding, i, tex_handle);
3225 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3229 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3234 //----------------------------------------------------------------------------------------------------------------------
3235 // vogl_gl_replayer::dump_current_shaders
3236 //----------------------------------------------------------------------------------------------------------------------
3237 void vogl_gl_replayer::dump_current_shaders()
3241 if (!m_pCur_context_state)
3246 const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3248 // Get the current program.
3249 GLuint current_program = 0;
3250 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(¤t_program));
3253 VOGL_ASSERT(replay_program == current_program);
3255 if (!current_program)
3258 // Get the attached shaders.
3259 GLsizei attached_shader_count = -1;
3260 GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3263 if (!attached_shader_count)
3266 vogl::vector<GLuint> shaders(attached_shader_count);
3267 GLsizei actual_shader_count = 0;
3268 GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3269 attached_shader_count,
3270 &actual_shader_count,
3274 VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3276 vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3277 cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3278 replay_program, m_pCur_context_state->m_cur_trace_program,
3279 attached_shader_count);
3281 // Get source from shaders.
3282 vogl::vector<GLchar> source; // Shared buffer for each iteration.
3283 for (GLsizei i = 0; i < attached_shader_count; ++i)
3285 const GLuint shader = shaders[i];
3286 GLint shader_type = 0;
3287 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3290 vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3292 GLint source_length = -1; // Includes NUL terminator.
3293 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3296 VOGL_ASSERT(source_length > 0);
3298 source.resize(source_length);
3299 GLint actual_length = 0; // Excludes NUL terminator!
3300 GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3303 VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3304 vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3306 vogl_printf("========\n");
3309 //----------------------------------------------------------------------------------------------------------------------
3310 // vogl_gl_replayer::handle_ShaderSource
3311 // Handle ShaderSource and ShaderSourceARB.
3312 //----------------------------------------------------------------------------------------------------------------------
3313 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3315 const vogl_client_memory_array trace_strings_glchar_ptr_array,
3316 const GLint *pTrace_lengths)
3320 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3322 // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3323 const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3324 const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3326 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3327 (trace_strings_count != static_cast<uint>(count)))
3329 process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3330 VOGL_METHOD_NAME, count, trace_strings_count);
3331 return cStatusHardFailure;
3334 if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3336 process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3337 VOGL_METHOD_NAME, count, trace_lengths_count);
3338 return cStatusHardFailure;
3341 vogl::vector<const GLcharARB *> strings(count);
3342 vogl::vector<GLint> lengths(count);
3344 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3346 vogl::vector<uint8_vec> blobs(count);
3348 for (GLsizei i = 0; i < count; i++)
3351 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3352 (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3357 lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3359 key_value_map::const_iterator it = map.find(i);
3360 if (it == map.end())
3364 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3365 VOGL_METHOD_NAME, i);
3366 return cStatusHardFailure;
3371 const uint8_vec *pBlob = it->second.get_blob();
3374 process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3375 return cStatusHardFailure;
3379 uint8_vec &blob = blobs[i];
3381 if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3383 if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3385 process_entrypoint_warning("%s: Length value (%u) stored in length array at index %u doesn't match string %u's length - changing to match\n", VOGL_METHOD_NAME, pTrace_lengths[i], i, blob.size());
3386 lengths[i] = blob.size();
3391 if ((blob.size()) && (blob.back() != '\0'))
3393 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3395 blob.push_back('\0');
3398 VOGL_ASSERT(blob.size() &&
3399 (blob.back() == '\0') &&
3400 (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3403 strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3406 if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3408 GL_ENTRYPOINT(glShaderSource)(replay_object,
3410 trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3411 pTrace_lengths ? lengths.get_ptr() : NULL);
3415 GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3417 trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3418 pTrace_lengths ? lengths.get_ptr() : NULL);
3423 //----------------------------------------------------------------------------------------------------------------------
3424 // vogl_gl_replayer::display_list_bind_callback
3425 // handle is in the trace namespace
3426 //----------------------------------------------------------------------------------------------------------------------
3427 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3431 vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3433 if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3435 if ((handle) && (target != GL_NONE))
3437 // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3438 pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3443 // TODO - right now the display list whitelist doens't let anything else get bound.
3444 pReplayer->process_entrypoint_warning("%s: Unsupported bind in display lists, namespace %s target %s trace handle %u\n", VOGL_FUNCTION_NAME, vogl_get_namespace_name(handle_namespace), g_gl_enums.find_gl_name(target), handle);
3448 //----------------------------------------------------------------------------------------------------------------------
3449 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3450 //----------------------------------------------------------------------------------------------------------------------
3451 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...) \
3452 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3453 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3455 result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3457 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...) \
3458 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3459 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3460 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3461 result = GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3463 result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3465 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...) \
3466 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3467 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3469 GL_ENTRYPOINT(e1)(__VA_ARGS__);
3471 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...) \
3472 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3473 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3474 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3475 GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3477 GL_ENTRYPOINT(e2)(__VA_ARGS__);
3479 //----------------------------------------------------------------------------------------------------------------------
3480 // vogl_replayer::process_gl_entrypoint_packet
3481 // This will be called during replaying, or when building display lists during state restoring.
3482 //----------------------------------------------------------------------------------------------------------------------
3483 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3485 m_pCur_gl_packet = &trace_packet;
3487 status_t status = cStatusOK;
3489 if (m_pPending_snapshot)
3491 status = process_applying_pending_snapshot();
3492 if (status != cStatusOK)
3496 if (m_pending_make_current_packet.is_valid())
3498 status = process_pending_make_current();
3499 if (status != cStatusOK)
3503 const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3505 m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3507 status = process_gl_entrypoint_packet_internal(trace_packet);
3509 if (status != cStatusResizeWindow)
3510 m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3512 m_pCur_gl_packet = NULL;
3517 //----------------------------------------------------------------------------------------------------------------------
3518 // vogl_replayer::process_gl_entrypoint_packet_internal
3519 // This will be called during replaying, or when building display lists during state restoring.
3520 //----------------------------------------------------------------------------------------------------------------------
3521 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3525 m_at_frame_boundary = false;
3527 const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3528 const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3530 if (m_flags & cGLReplayerDebugMode)
3531 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3533 if (m_flags & cGLReplayerDebugMode)
3534 dump_packet_as_func_call(trace_packet);
3536 if (m_flags & cGLReplayerDumpAllPackets)
3537 print_detailed_context(cDebugConsoleMessage);
3539 if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3540 return process_internal_trace_command(gl_entrypoint_packet);
3542 status_t status = cStatusOK;
3544 if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3546 status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3547 if (status != cStatusOK)
3551 bool processed_glx_packet = true;
3552 switch (entrypoint_id)
3554 case VOGL_ENTRYPOINT_glXDestroyContext:
3556 const Display *dpy = m_pWindow->get_display();
3558 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3559 GLXContext replay_context = remap_context(trace_context);
3561 if ((trace_context) && (!replay_context))
3563 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3564 return cStatusHardFailure;
3567 if (trace_context == m_cur_trace_context)
3569 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3570 VOGL_METHOD_NAME, (uint64_t)trace_context);
3572 m_cur_trace_context = 0;
3573 m_cur_replay_context = 0;
3574 m_pCur_context_state = NULL;
3577 GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3579 destroy_context(trace_context);
3583 case VOGL_ENTRYPOINT_glXMakeCurrent:
3584 case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3586 Bool trace_result = trace_packet.get_return_value<Bool>();
3588 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3590 // pContext_state can be NULL!
3591 context_state *pContext_state = get_trace_context_state(trace_context);
3592 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3594 if ((trace_context) && (!replay_context))
3596 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3597 return cStatusHardFailure;
3600 int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3601 VOGL_NOTE_UNUSED(viewport_x);
3602 int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3603 VOGL_NOTE_UNUSED(viewport_y);
3604 int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3605 VOGL_NOTE_UNUSED(viewport_width);
3606 int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3607 VOGL_NOTE_UNUSED(viewport_height);
3608 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3609 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3611 // We may need to defer the make current until the window is the proper size, because the initial GL viewport's state depends on the Window size. Ugh.
3612 if ((trace_context) && (trace_result))
3614 if ((win_width) && (win_height))
3616 if (!(m_flags & cGLReplayerLockWindowDimensions))
3618 if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3620 m_pending_make_current_packet = *m_pCur_gl_packet;
3622 status = trigger_pending_window_resize(win_width, win_height);
3624 vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3630 if (status != cStatusResizeWindow)
3632 const Display *dpy = m_pWindow->get_display();
3633 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3635 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3640 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3641 return cStatusHardFailure;
3645 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3650 m_cur_trace_context = trace_context;
3651 m_cur_replay_context = replay_context;
3652 m_pCur_context_state = pContext_state;
3656 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3660 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3661 viewport_x, viewport_y,
3662 viewport_width, viewport_height,
3663 win_width, win_height);
3666 if (m_cur_replay_context)
3668 if (!handle_context_made_current())
3669 return cStatusHardFailure;
3676 case VOGL_ENTRYPOINT_glXQueryVersion:
3678 int major = 0, minor = 0;
3679 Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3680 process_entrypoint_message("%s: glXQueryVersion returned major %u minor %u status %u, trace recorded major %u minor %u status %u\n", VOGL_METHOD_NAME, major, minor, status,
3681 *trace_packet.get_param_client_memory<int>(1),
3682 *trace_packet.get_param_client_memory<int>(2),
3683 trace_packet.get_return_value<Bool>());
3687 case VOGL_ENTRYPOINT_glXChooseFBConfig:
3692 case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3697 case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3702 case VOGL_ENTRYPOINT_glXGetProcAddress:
3703 case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3705 const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3706 vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3708 void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3710 if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3712 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3713 (const char *)procName,
3714 (pFunc != NULL) ? "succeeded" : "failed",
3715 (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3720 case VOGL_ENTRYPOINT_glXCreateNewContext:
3722 Display *dpy = m_pWindow->get_display();
3723 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3724 int render_type = trace_packet.get_param_value<GLint>(2);
3726 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3727 GLXContext replay_share_context = remap_context(trace_share_context);
3729 if ((trace_share_context) && (!replay_share_context))
3731 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3734 Bool direct = trace_packet.get_param_value<Bool>(4);
3735 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3737 if (m_flags & cGLReplayerForceDebugContexts)
3739 process_entrypoint_warning("%s: glxCreateNewContext() called but we're trying to force debug contexts, which requires us to call glXCreateContextAttribsARB(). This may fail if the user has called glXCreateWindow().\n", VOGL_METHOD_NAME);
3741 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3742 if (status != cStatusOK)
3747 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3749 if (!replay_context)
3753 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3754 return cStatusHardFailure;
3758 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3766 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3767 VOGL_NOTE_UNUSED(pContext_state);
3771 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3778 case VOGL_ENTRYPOINT_glXCreateContext:
3780 Display *dpy = m_pWindow->get_display();
3782 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3783 GLXContext replay_share_context = remap_context(trace_share_context);
3785 if ((trace_share_context) && (!replay_share_context))
3787 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3790 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3791 Bool direct = trace_packet.get_param_value<Bool>(3);
3792 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3794 if (m_flags & cGLReplayerForceDebugContexts)
3796 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3797 if (status != cStatusOK)
3802 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3804 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3806 if (!replay_context)
3810 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3811 return cStatusHardFailure;
3815 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3823 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3824 VOGL_NOTE_UNUSED(pContext_state);
3828 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3835 case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3837 Display *dpy = m_pWindow->get_display();
3838 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3840 vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3841 GLXContext replay_share_context = remap_context(trace_share_context);
3843 if ((trace_share_context) && (!replay_share_context))
3845 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3848 Bool direct = trace_packet.get_param_value<Bool>(3);
3849 const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3850 const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3852 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3854 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3855 if (status != cStatusOK)
3860 case VOGL_ENTRYPOINT_glXSwapBuffers:
3862 check_program_binding_shadow();
3864 if (m_flags & cGLReplayerLowLevelDebugMode)
3866 if (!validate_program_and_shader_handle_tables())
3867 vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3868 if (!validate_textures())
3869 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3872 const Display *dpy = m_pWindow->get_display();
3873 GLXDrawable drawable = m_pWindow->get_xwindow();
3875 if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3877 snapshot_backbuffer();
3880 if (m_dump_frontbuffer_filename.has_content())
3882 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3883 m_dump_frontbuffer_filename.clear();
3886 GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3888 if (m_swap_sleep_time)
3889 vogl_sleep(m_swap_sleep_time);
3891 status = cStatusNextFrame;
3893 m_at_frame_boundary = true;
3895 if (m_flags & cGLReplayerDebugMode)
3897 vogl_debug_printf("%s: glXSwapBuffers() processed at end of frame %u, swap %u, last GL call counter %" PRIu64 "\n", VOGL_METHOD_NAME, m_frame_index, m_total_swaps, m_last_parsed_call_counter);
3903 m_frame_draw_counter = 0;
3905 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3906 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3907 if ((win_width) && (win_height))
3909 if (!(m_flags & cGLReplayerLockWindowDimensions))
3911 if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3913 // TODO: This resize might need to be deferred until the window system actually resizes the window.
3914 //m_pWindow->resize(win_width, win_height);
3915 trigger_pending_window_resize(win_width, win_height);
3917 vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3924 case VOGL_ENTRYPOINT_glXWaitX:
3926 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3928 VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3932 case VOGL_ENTRYPOINT_glXWaitGL:
3934 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3936 VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3940 case VOGL_ENTRYPOINT_glXIsDirect:
3942 const Display *dpy = m_pWindow->get_display();
3944 vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3945 GLXContext replay_context = remap_context(trace_context);
3947 Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3948 Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3950 if (replay_is_direct != trace_is_direct)
3952 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3957 case VOGL_ENTRYPOINT_glXGetCurrentContext:
3959 GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3960 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3962 if ((replay_context != 0) != (trace_context != 0))
3964 process_entrypoint_warning("%s: glXGetCurrentContext() returned different results while replaying (0x%" PRIX64 ") vs tracing (0x%" PRIX64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_context, (uint64_t)trace_context);
3969 case VOGL_ENTRYPOINT_glXCreateWindow:
3970 case VOGL_ENTRYPOINT_glXDestroyWindow:
3971 case VOGL_ENTRYPOINT_glXChooseVisual:
3972 case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3973 case VOGL_ENTRYPOINT_glXQueryDrawable:
3974 case VOGL_ENTRYPOINT_glXQueryExtension:
3975 case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3976 case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3977 case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3978 case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3979 case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3980 case VOGL_ENTRYPOINT_glXQueryContext:
3981 case VOGL_ENTRYPOINT_glXGetClientString:
3982 case VOGL_ENTRYPOINT_glXGetConfig:
3983 case VOGL_ENTRYPOINT_glXGetFBConfigs:
3990 processed_glx_packet = false;
3995 if (processed_glx_packet)
3997 // TODO: Check for GLX errors?
4001 if (!m_cur_replay_context)
4003 process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
4004 return cStatusSoftFailure;
4007 VOGL_ASSERT(m_pCur_context_state);
4008 m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
4010 #ifdef VOGL_BUILD_DEBUG
4011 VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
4014 // Add call to current display list
4015 if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
4017 if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
4019 if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
4020 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not whitelisted for display list usage by vogl.\n", VOGL_FUNCTION_NAME);
4022 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
4026 if (!get_shared_state()->m_shadow_state.m_display_lists.add_packet_to_list(get_context_state()->m_current_display_list_handle, entrypoint_id, trace_packet))
4028 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
4033 switch (entrypoint_id)
4035 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4036 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4037 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4038 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4039 case VOGL_ENTRYPOINT_##name: \
4040 { if (!GL_ENTRYPOINT(name)) { process_entrypoint_error("vogl_gl_replayer::process_gl_entrypoint_packet_internal: Can't call NULL GL entrypoint %s (maybe a missing extension?)\n", #name); } else \
4041 GL_ENTRYPOINT(name)(
4042 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4043 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4044 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4045 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4048 #include "gl_glx_simple_replay_funcs.inc"
4049 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4050 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4051 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4052 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4053 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4055 case VOGL_ENTRYPOINT_glXUseXFont:
4057 const key_value_map &key_value_map = trace_packet.get_key_value_map();
4059 const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4060 if ((!pFont_name) || (pFont_name->is_empty()))
4062 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4066 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4069 process_entrypoint_warning("%s: Couldn't load X font %s - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4073 GLint first = trace_packet.get_param_value<int>(1);
4074 GLint count = trace_packet.get_param_value<int>(2);
4075 int trace_list_base = trace_packet.get_param_value<int>(3);
4076 GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4078 GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4080 XFreeFont(m_pWindow->get_display(), pFont);
4082 if (get_context_state()->is_composing_display_list())
4084 process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4088 if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4090 process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4098 case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4100 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4102 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4104 if ((status = post_draw_call()) != cStatusOK)
4109 case VOGL_ENTRYPOINT_glBlitFramebuffer:
4111 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4113 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4115 if ((status = post_draw_call()) != cStatusOK)
4120 case VOGL_ENTRYPOINT_glBegin:
4122 if (m_pCur_context_state->m_inside_gl_begin)
4124 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4126 m_pCur_context_state->m_inside_gl_begin = true;
4128 g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4132 case VOGL_ENTRYPOINT_glEnd:
4134 if (!m_pCur_context_state->m_inside_gl_begin)
4136 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4138 m_pCur_context_state->m_inside_gl_begin = false;
4140 g_vogl_actual_gl_entrypoints.m_glEnd();
4142 if ((status = post_draw_call()) != cStatusOK)
4147 case VOGL_ENTRYPOINT_glGetError:
4149 // TODO: Compare trace error vs. replay error
4153 case VOGL_ENTRYPOINT_glGetStringi:
4155 if (!benchmark_mode())
4157 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4158 trace_packet.get_param_value<GLenum>(0),
4159 trace_packet.get_param_value<GLuint>(1));
4160 VOGL_NOTE_UNUSED(pStr);
4162 // TODO: Compare vs. trace's?
4167 case VOGL_ENTRYPOINT_glGetString:
4169 if (!benchmark_mode())
4171 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4172 trace_packet.get_param_value<GLenum>(0));
4173 VOGL_NOTE_UNUSED(pStr);
4175 // TODO: Compare vs. trace's?
4180 case VOGL_ENTRYPOINT_glGenFramebuffers:
4181 case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4183 if (!gen_handles(get_context_state()->m_framebuffers,
4184 trace_packet.get_param_value<GLsizei>(0),
4185 static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4186 (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4187 return cStatusHardFailure;
4191 case VOGL_ENTRYPOINT_glBindFramebuffer:
4192 case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4194 GLenum target = trace_packet.get_param_value<GLenum>(0);
4195 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4197 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4199 SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4203 case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4204 case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4206 if (!benchmark_mode())
4208 GLenum target = trace_packet.get_param_value<GLenum>(0);
4209 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4210 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4211 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4212 uint trace_params_count = trace_params_size / sizeof(GLint);
4214 int n = g_gl_enums.get_pname_count(pname);
4217 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4218 return cStatusSoftFailure;
4220 else if (n < static_cast<int>(trace_params_count))
4222 process_entrypoint_error("%s: Expected %i GLint's for GL pname 0x%08X, but trace only contains %i GLint's\n", VOGL_METHOD_NAME, n, pname, trace_params_count);
4223 return cStatusSoftFailure;
4227 vogl::growable_array<GLint, 16> params(n + 1);
4228 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4230 SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4232 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4234 if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4236 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s target %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname), g_gl_enums.find_gl_name(target));
4243 case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4244 case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4247 SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4249 GLenum trace_status = trace_packet.get_return_value<GLenum>();
4250 if (result != trace_status)
4252 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4256 case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4258 delete_handles(get_context_state()->m_framebuffers, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteFramebuffers));
4261 case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4263 delete_handles(get_context_state()->m_framebuffers, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteFramebuffersEXT));
4266 case VOGL_ENTRYPOINT_glFramebufferTexture:
4268 GLenum target = trace_packet.get_param_value<GLenum>(0);
4269 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4270 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4271 GLuint replay_texture = trace_texture;
4272 GLint level = trace_packet.get_param_value<GLint>(3);
4274 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4277 process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4280 GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4284 case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4285 case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4287 GLenum target = trace_packet.get_param_value<GLenum>(0);
4288 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4289 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4290 GLuint replay_texture = trace_texture;
4291 GLint level = trace_packet.get_param_value<GLint>(3);
4292 GLint layer = trace_packet.get_param_value<GLint>(4);
4294 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4297 process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4300 SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4304 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4305 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4306 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4307 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4308 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4309 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4311 GLenum target = trace_packet.get_param_value<GLenum>(0);
4312 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4313 GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4314 GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4315 GLuint replay_texture = trace_texture;
4316 GLint level = trace_packet.get_param_value<GLint>(4);
4318 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4321 process_entrypoint_warning("%s: Couldn't map trace texture ID %u to GL texture ID, using trace texture ID instead\n", VOGL_METHOD_NAME, trace_texture);
4324 switch (entrypoint_id)
4326 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4327 GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4329 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4330 GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4332 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4333 GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4335 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4336 GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4338 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4339 GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4341 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4342 GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4350 case VOGL_ENTRYPOINT_glGenTextures:
4352 if (!gen_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenTextures), NULL, GL_NONE))
4353 return cStatusHardFailure;
4356 case VOGL_ENTRYPOINT_glGenTexturesEXT:
4358 if (!gen_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenTexturesEXT), NULL, GL_NONE))
4359 return cStatusHardFailure;
4362 case VOGL_ENTRYPOINT_glDeleteTextures:
4364 delete_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteTextures));
4367 case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4369 delete_handles(get_shared_state()->m_shadow_state.m_textures, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteTexturesEXT));
4372 case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4374 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4376 GLuint trace_texture = texture;
4377 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4379 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4382 VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4384 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4386 if (!check_gl_error())
4387 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4392 case VOGL_ENTRYPOINT_glBindTexture:
4393 case VOGL_ENTRYPOINT_glBindTextureEXT:
4395 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4397 GLuint trace_texture = texture;
4398 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4400 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4403 SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4405 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4407 if (!check_gl_error())
4408 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4413 case VOGL_ENTRYPOINT_glBindSampler:
4415 GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4416 GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4419 case VOGL_ENTRYPOINT_glDeleteSamplers:
4421 delete_handles(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteSamplers));
4424 case VOGL_ENTRYPOINT_glGenSamplers:
4426 if (!gen_handles(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenSamplers), NULL))
4427 return cStatusHardFailure;
4431 case VOGL_ENTRYPOINT_glSamplerParameterf:
4433 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4434 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4435 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4438 case VOGL_ENTRYPOINT_glSamplerParameteri:
4440 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4441 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4442 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4445 case VOGL_ENTRYPOINT_glSamplerParameterfv:
4447 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4448 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4449 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4452 case VOGL_ENTRYPOINT_glSamplerParameteriv:
4454 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4455 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4456 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4459 case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4461 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4462 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4463 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4466 case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4468 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4469 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4470 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4473 case VOGL_ENTRYPOINT_glGenBuffers:
4474 case VOGL_ENTRYPOINT_glGenBuffersARB:
4476 uint n = trace_packet.get_param_value<GLsizei>(0);
4477 const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4479 if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4481 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4482 return cStatusHardFailure;
4486 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4487 return cStatusHardFailure;
4492 for (uint i = 0; i < n; i++)
4494 if (pTrace_handles[i])
4495 get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4501 case VOGL_ENTRYPOINT_glDeleteBuffers:
4502 case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4504 GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4505 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4506 uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4508 if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4510 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4511 return cStatusHardFailure;
4514 for (GLsizei iter = 0; iter < trace_n; iter++)
4516 GLuint trace_id = pTrace_ids[iter];
4520 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4522 process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4525 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4526 if (it == get_shared_state()->m_buffers.end())
4528 process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4532 GLuint replay_id = it->second;
4534 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
4536 for (uint i = 0; i < mapped_bufs.size(); i++)
4538 if (mapped_bufs[i].m_buffer == replay_id)
4540 process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4542 mapped_bufs.erase_unordered(i);
4548 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4549 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4551 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4555 case VOGL_ENTRYPOINT_glGenProgramsARB:
4557 // arb program objects
4558 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4560 if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4561 return cStatusHardFailure;
4563 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4564 if (pTrace_programs[i])
4565 get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4569 case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4571 // arb program objects
4572 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4574 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4575 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4577 delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4580 case VOGL_ENTRYPOINT_glBindProgramARB:
4582 // arb program objects
4583 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4585 GLuint trace_program = program;
4586 gl_handle_hash_map::const_iterator it;
4589 it = get_shared_state()->m_arb_programs.find(program);
4590 if (it != get_shared_state()->m_arb_programs.end())
4591 program = it->second;
4593 process_entrypoint_warning("%s: Couldn't map trace handle %u to GL handle, using trace handle instead (handle may not have been genned)\n", VOGL_METHOD_NAME, program);
4598 VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4600 if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4604 if (it == get_shared_state()->m_arb_programs.end())
4605 get_shared_state()->m_arb_programs.insert(trace_program, program);
4607 get_shared_state()->m_arb_program_targets[trace_program] = target;
4612 process_entrypoint_warning("%s: GL error while binding ARB program, trace handle %u GL handle %u target %s\n", VOGL_METHOD_NAME, trace_program, program, g_gl_enums.find_gl_name(target));
4613 return cStatusGLError;
4618 case VOGL_ENTRYPOINT_glIsProgramARB:
4620 if (!benchmark_mode())
4622 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4624 GLuint trace_program = program;
4625 program = map_handle(get_shared_state()->m_arb_programs, program);
4627 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4628 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4630 if (trace_result != replay_result)
4631 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u, trace ARB program: %u replay ARB program %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result), trace_program, program);
4636 case VOGL_ENTRYPOINT_glGenQueries:
4637 case VOGL_ENTRYPOINT_glGenQueriesARB:
4639 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4640 vogl::growable_array<GLuint, 16> replay_handles(n);
4642 if (!gen_handles(get_shared_state()->m_queries, n, static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), (entrypoint_id == VOGL_ENTRYPOINT_glGenQueries) ? GL_ENTRYPOINT(glGenQueries) : GL_ENTRYPOINT(glGenQueriesARB), replay_handles.get_ptr()))
4643 return cStatusHardFailure;
4645 for (GLsizei i = 0; i < n; i++)
4646 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4650 case VOGL_ENTRYPOINT_glDeleteQueries:
4651 case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4653 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4654 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4658 for (GLsizei i = 0; i < n; i++)
4660 GLuint trace_id = pTrace_ids[i];
4663 gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4664 if (it != get_shared_state()->m_queries.end())
4665 get_shared_state()->m_query_targets.erase(it->second);
4669 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4670 delete_handles(get_shared_state()->m_queries, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteQueries));
4672 delete_handles(get_shared_state()->m_queries, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteQueriesARB));
4676 case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4678 if (!gen_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenRenderbuffersEXT), NULL, GL_NONE))
4679 return cStatusHardFailure;
4682 case VOGL_ENTRYPOINT_glGenRenderbuffers:
4684 if (!gen_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenRenderbuffers), NULL, GL_NONE))
4685 return cStatusHardFailure;
4688 case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4690 delete_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteRenderbuffersEXT));
4693 case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4695 delete_handles(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteRenderbuffers));
4698 case VOGL_ENTRYPOINT_glIsRenderbuffer:
4700 if (!benchmark_mode())
4702 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4703 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4704 if (replay_result != trace_result)
4706 process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4711 case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4713 if (!benchmark_mode())
4715 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4716 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4717 if (replay_result != trace_result)
4719 process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4724 case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4726 GL_ENTRYPOINT(glBindRenderbufferEXT)(trace_packet.get_param_value<GLenum>(0), map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(1)));
4729 case VOGL_ENTRYPOINT_glBindRenderbuffer:
4731 GL_ENTRYPOINT(glBindRenderbuffer)(trace_packet.get_param_value<GLenum>(0), map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(1)));
4734 case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4736 GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4737 trace_packet.get_param_value<GLenum>(0),
4738 trace_packet.get_param_value<GLenum>(1),
4739 trace_packet.get_param_value<GLenum>(2),
4740 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4743 case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4745 GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4746 trace_packet.get_param_value<GLenum>(0),
4747 trace_packet.get_param_value<GLenum>(1),
4748 trace_packet.get_param_value<GLenum>(2),
4749 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4752 case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4753 case VOGL_ENTRYPOINT_glUseProgram:
4755 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4756 handle_use_program(trace_handle, entrypoint_id);
4759 case VOGL_ENTRYPOINT_glProgramParameteri:
4760 case VOGL_ENTRYPOINT_glProgramParameteriARB:
4761 case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4763 VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4765 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4767 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4768 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4769 else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4770 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4772 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4776 case VOGL_ENTRYPOINT_glBindFragDataLocation:
4777 case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4779 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4781 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4783 if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4784 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4786 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4790 case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4792 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4794 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4796 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4800 case VOGL_ENTRYPOINT_glValidateProgramARB:
4802 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4804 programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4806 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4810 case VOGL_ENTRYPOINT_glValidateProgram:
4812 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4814 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4816 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4820 case VOGL_ENTRYPOINT_glCreateProgram:
4821 case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4823 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4826 GLuint replay_handle;
4828 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4829 replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4831 replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4833 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4835 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4836 return cStatusHardFailure;
4840 case VOGL_ENTRYPOINT_glDeleteProgram:
4842 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4843 handle_delete_program(trace_handle);
4847 case VOGL_ENTRYPOINT_glDeleteObjectARB:
4849 GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4850 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4852 if (target == VOGL_SHADER_OBJECT)
4853 handle_delete_shader(trace_handle);
4854 else if (target == VOGL_PROGRAM_OBJECT)
4855 handle_delete_program(trace_handle);
4858 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4860 process_entrypoint_error("%s: Failed determining if trace handle %u relay handle %u is a shader or program -- unable to delete object!\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
4861 return cStatusSoftFailure;
4866 case VOGL_ENTRYPOINT_glDeleteShader:
4868 GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4869 handle_delete_shader(trace_shader);
4873 case VOGL_ENTRYPOINT_glCreateShader:
4874 case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4876 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4879 GLuint replay_handle;
4881 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4882 replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4884 replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4886 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4888 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4889 return cStatusHardFailure;
4893 case VOGL_ENTRYPOINT_glAttachShader:
4895 GL_ENTRYPOINT(glAttachShader)(
4896 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4897 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4900 case VOGL_ENTRYPOINT_glAttachObjectARB:
4902 GL_ENTRYPOINT(glAttachObjectARB)(
4903 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4904 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4907 case VOGL_ENTRYPOINT_glDetachShader:
4909 handle_detach_shader(entrypoint_id);
4913 case VOGL_ENTRYPOINT_glDetachObjectARB:
4915 GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4917 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4919 if (target == VOGL_SHADER_OBJECT)
4920 handle_detach_shader(entrypoint_id);
4923 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4924 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4929 case VOGL_ENTRYPOINT_glBindAttribLocation:
4931 GL_ENTRYPOINT(glBindAttribLocation)(
4932 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4933 trace_packet.get_param_value<GLuint>(1),
4934 trace_packet.get_param_client_memory<GLchar>(2));
4937 case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4939 GL_ENTRYPOINT(glBindAttribLocationARB)(
4940 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4941 trace_packet.get_param_value<GLuint>(1),
4942 trace_packet.get_param_client_memory<GLcharARB>(2));
4945 case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4947 if (!benchmark_mode())
4949 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4950 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4952 int n = g_gl_enums.get_pname_count(pname);
4955 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4956 return cStatusSoftFailure;
4960 vogl::growable_array<GLint, 16> params(n + 1);
4961 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4963 GL_ENTRYPOINT(glGetObjectParameterivARB)(
4964 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4968 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4970 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4972 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
4978 case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4980 if (!benchmark_mode())
4982 GLenum target = trace_packet.get_param_value<GLenum>(0);
4983 GLenum value = trace_packet.get_param_value<GLenum>(1);
4984 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4986 int n = g_gl_enums.get_pname_count(value);
4989 process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4990 return cStatusSoftFailure;
4994 vogl::growable_array<GLint, 16> data(n + 1);
4995 data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4997 GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4999 VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5001 GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
5002 if (data[0] != trace_data)
5004 process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
5005 vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
5013 case VOGL_ENTRYPOINT_glGetBufferPointerv:
5015 if (!benchmark_mode())
5017 GLvoid *pReplay_ptr = NULL;
5018 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
5020 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
5021 vogl_trace_ptr_value first_trace_ptr = trace_void_ptr_array.get_ptr() ? trace_void_ptr_array.get_element<vogl_trace_ptr_value>(0) : 0;
5023 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
5025 process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
5026 vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
5032 case VOGL_ENTRYPOINT_glShaderSource:
5033 case VOGL_ENTRYPOINT_glShaderSourceARB:
5035 const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
5036 trace_packet.get_param_value<GLsizei>(1),
5037 trace_packet.get_param_client_memory_array(2),
5038 trace_packet.get_param_client_memory<const GLint>(3));
5039 if (status != cStatusOK)
5043 case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5045 GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5046 GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5049 GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5052 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5053 return cStatusSoftFailure;
5057 vogl::vector<GLchar> log(length);
5059 GLsizei actual_length = 0;
5060 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5064 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_object, replay_object, log.get_ptr());
5070 case VOGL_ENTRYPOINT_glGetPointerv:
5072 if (!benchmark_mode())
5075 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5077 // TODO: Differ vs. trace's in some way?
5082 case VOGL_ENTRYPOINT_glGetInfoLogARB:
5084 GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5085 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5087 GLsizei length = -1;
5088 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
5091 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5092 return cStatusSoftFailure;
5096 vogl::vector<GLcharARB> log(length);
5098 GLsizei actual_length = 0;
5099 GL_ENTRYPOINT(glGetInfoLogARB)(replay_object, length, &actual_length, log.get_ptr());
5103 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_object, replay_object, log.get_ptr());
5109 case VOGL_ENTRYPOINT_glGetUniformLocation:
5111 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5112 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5113 GLint trace_loc = trace_packet.get_return_value<GLint>();
5117 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5119 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5123 process_entrypoint_warning("%s: glGetUniformLocation: Function succeeded during trace, but failed during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5128 process_entrypoint_warning("%s: glGetUniformLocation: Function failed during trace, but succeeded during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5131 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5132 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5133 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5135 glsl_program_state &state = it->second;
5136 state.m_uniform_locations.erase(trace_loc);
5137 state.m_uniform_locations.insert(trace_loc, replay_loc);
5144 case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5146 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5147 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5148 GLint trace_loc = trace_packet.get_return_value<GLint>();
5152 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5154 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5158 process_entrypoint_warning("%s: glGetUniformLocationARB: Function succeeded during trace, but failed during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5163 process_entrypoint_warning("%s: glGetUniformLocationARB: Function failed during trace, but succeeded during replay! (name: %s trace_handle: %u, trace_loc: %i)\n", VOGL_METHOD_NAME, (const char *)pName, trace_handle, trace_loc);
5166 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5167 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5168 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5170 glsl_program_state &state = it->second;
5171 state.m_uniform_locations.erase(trace_loc);
5172 state.m_uniform_locations.insert(trace_loc, replay_loc);
5179 case VOGL_ENTRYPOINT_glGetActiveAttrib:
5180 case VOGL_ENTRYPOINT_glGetActiveUniform:
5182 if (!benchmark_mode())
5184 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5185 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5187 GLuint index = trace_packet.get_param_value<GLuint>(1);
5188 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5190 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5191 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5192 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5193 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5195 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5201 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5202 GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5204 GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5206 bool mismatch = false;
5208 GLsizei trace_len = 0;
5211 trace_len = pTrace_length[0];
5212 if (trace_len != len)
5216 GLint trace_size = 0;
5219 trace_size = pTrace_size[0];
5220 if (trace_size != size)
5224 GLenum trace_type = 0;
5227 trace_type = pTrace_type[0];
5228 if (trace_type != type)
5232 if ((bufSize) && (pTrace_name))
5234 uint n = vogl_strlen((const char *)pTrace_name) + 1;
5235 if (bufSize < (GLsizei)n)
5237 else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5243 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5244 vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5245 (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5246 vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5247 (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5253 case VOGL_ENTRYPOINT_glGetAttachedShaders:
5255 if (!benchmark_mode())
5257 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5258 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5260 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5262 vogl::growable_array<GLuint, 16> shaders(max_count);
5264 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5266 // TODO: Diff results
5271 case VOGL_ENTRYPOINT_glGetAttribLocation:
5273 if (!benchmark_mode())
5275 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5276 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5278 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5280 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5281 GLint trace_result = trace_packet.get_return_value<GLint>();
5283 if (replay_result != trace_result)
5285 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5286 vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5292 case VOGL_ENTRYPOINT_glGetProgramivARB:
5294 if (!benchmark_mode())
5296 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5297 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5298 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5299 uint params_count = params_size / sizeof(GLint);
5301 int n = g_gl_enums.get_pname_count(pname);
5304 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5305 return cStatusSoftFailure;
5309 vogl::growable_array<GLint, 16> params(n + 1);
5310 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5312 GL_ENTRYPOINT(glGetProgramivARB)(
5313 trace_packet.get_param_value<GLenum>(0),
5317 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5319 if (params_count != static_cast<uint>(n))
5321 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5323 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5325 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5332 case VOGL_ENTRYPOINT_glGetProgramiv:
5334 if (!benchmark_mode())
5336 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5337 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5339 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5341 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5342 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5343 uint params_count = params_size / sizeof(GLint);
5345 int n = g_gl_enums.get_pname_count(pname);
5348 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5349 return cStatusSoftFailure;
5353 vogl::growable_array<GLint, 16> params(n + 1);
5354 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5356 GL_ENTRYPOINT(glGetProgramiv)(
5361 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5363 if (params_count != static_cast<uint>(n))
5365 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5367 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5369 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5376 case VOGL_ENTRYPOINT_glLinkProgram:
5377 case VOGL_ENTRYPOINT_glLinkProgramARB:
5378 case VOGL_ENTRYPOINT_glProgramBinary:
5380 handle_link_program(entrypoint_id);
5384 case VOGL_ENTRYPOINT_glCompileShader:
5386 GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5389 case VOGL_ENTRYPOINT_glCompileShaderARB:
5391 GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5394 case VOGL_ENTRYPOINT_glGetShaderiv:
5396 if (!benchmark_mode())
5398 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5399 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5401 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5404 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5406 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, ¶ms);
5408 if ((pClient_params) && (*pClient_params != params))
5410 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5411 vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5417 case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5419 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5420 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5422 GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5423 const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5424 VOGL_NOTE_UNUSED(pTrace_length);
5425 const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5426 VOGL_NOTE_UNUSED(pTrace_info_log);
5428 vogl::growable_array<GLchar, 512> log(trace_max_length);
5430 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5434 process_entrypoint_message("%s: Info log for trace object %u, replay object %u:\n%s\n", VOGL_METHOD_NAME, trace_handle, replay_handle, log.get_ptr());
5439 case VOGL_ENTRYPOINT_glGetBooleanv:
5441 if (!benchmark_mode())
5443 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5444 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5446 int n = g_gl_enums.get_pname_count(pname);
5449 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X (%s)\n", VOGL_METHOD_NAME, pname, g_gl_enums.find_gl_name(pname));
5450 return cStatusSoftFailure;
5454 vogl::growable_array<GLboolean, 16> params(n + 1);
5455 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5457 GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5459 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5461 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5463 process_entrypoint_warning("%s: Replay's returned GLboolean data for pname 0x%08X (%s) differed from trace's\n", VOGL_METHOD_NAME, pname, g_gl_enums.find_gl_name(pname));
5470 case VOGL_ENTRYPOINT_glGetDoublev:
5472 if (!benchmark_mode())
5474 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5475 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5477 int n = g_gl_enums.get_pname_count(pname);
5480 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5481 return cStatusSoftFailure;
5485 vogl::growable_array<GLdouble, 17> params(n + 1);
5486 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5488 GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5490 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5492 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5494 process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5501 case VOGL_ENTRYPOINT_glGetFloatv:
5503 if (!benchmark_mode())
5505 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5506 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5507 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5509 int n = g_gl_enums.get_pname_count(pname);
5512 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5513 return cStatusSoftFailure;
5516 vogl::growable_array<GLfloat, 17> params(n + 1);
5517 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5519 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5521 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5523 if (static_cast<int>(trace_params_count) < n)
5524 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5525 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5527 process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5533 case VOGL_ENTRYPOINT_glGetIntegerv:
5535 if (!benchmark_mode())
5537 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5538 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5539 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5541 int n = g_gl_enums.get_pname_count(pname);
5544 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5545 return cStatusSoftFailure;
5548 vogl::growable_array<GLint, 16> params(n + 1);
5549 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5551 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5553 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5555 bool is_binding = false;
5558 case GL_ARRAY_BUFFER_BINDING:
5559 case GL_COLOR_ARRAY_BUFFER_BINDING:
5560 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5561 case GL_DRAW_FRAMEBUFFER_BINDING:
5562 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5563 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5564 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5565 case GL_INDEX_ARRAY_BUFFER_BINDING:
5566 case GL_NORMAL_ARRAY_BUFFER_BINDING:
5567 case GL_PIXEL_PACK_BUFFER_BINDING:
5568 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5569 case GL_PROGRAM_PIPELINE_BINDING:
5570 case GL_READ_FRAMEBUFFER_BINDING:
5571 case GL_RENDERBUFFER_BINDING:
5572 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5573 case GL_SHADER_STORAGE_BUFFER_BINDING:
5574 case GL_TEXTURE_BINDING_1D:
5575 case GL_TEXTURE_BINDING_1D_ARRAY:
5576 case GL_TEXTURE_BINDING_2D:
5577 case GL_TEXTURE_BINDING_2D_ARRAY:
5578 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5579 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5580 case GL_TEXTURE_BINDING_3D:
5581 case GL_TEXTURE_BINDING_BUFFER:
5582 case GL_TEXTURE_BINDING_CUBE_MAP:
5583 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5584 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5585 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5586 case GL_UNIFORM_BUFFER_BINDING:
5587 case GL_VERTEX_ARRAY_BINDING:
5588 case GL_VERTEX_ARRAY_BUFFER_BINDING:
5589 case GL_CURRENT_PROGRAM:
5598 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5601 if (static_cast<int>(trace_params_count) < n)
5603 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5605 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5607 process_entrypoint_warning("%s: Replay's returned GLint data differed from trace's, pname %s\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(pname));
5608 for (int i = 0; i < n; i++)
5609 vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5616 // glProgramUniform's
5617 case VOGL_ENTRYPOINT_glProgramUniform1f:
5619 set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5622 case VOGL_ENTRYPOINT_glProgramUniform1i:
5624 set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5627 case VOGL_ENTRYPOINT_glProgramUniform1ui:
5629 set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5632 case VOGL_ENTRYPOINT_glProgramUniform2f:
5634 set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5637 case VOGL_ENTRYPOINT_glProgramUniform2i:
5639 set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5642 case VOGL_ENTRYPOINT_glProgramUniform2ui:
5644 set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5647 case VOGL_ENTRYPOINT_glProgramUniform3f:
5649 set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5652 case VOGL_ENTRYPOINT_glProgramUniform3i:
5654 set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5657 case VOGL_ENTRYPOINT_glProgramUniform3ui:
5659 set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5662 case VOGL_ENTRYPOINT_glProgramUniform4f:
5664 set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5667 case VOGL_ENTRYPOINT_glProgramUniform4i:
5669 set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5672 case VOGL_ENTRYPOINT_glProgramUniform4ui:
5674 set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5677 case VOGL_ENTRYPOINT_glProgramUniform1fv:
5679 set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5682 case VOGL_ENTRYPOINT_glProgramUniform2fv:
5684 set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5687 case VOGL_ENTRYPOINT_glProgramUniform3fv:
5689 set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5692 case VOGL_ENTRYPOINT_glProgramUniform4fv:
5694 set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5697 case VOGL_ENTRYPOINT_glProgramUniform1iv:
5699 set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5702 case VOGL_ENTRYPOINT_glProgramUniform2iv:
5704 set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5707 case VOGL_ENTRYPOINT_glProgramUniform3iv:
5709 set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5712 case VOGL_ENTRYPOINT_glProgramUniform4iv:
5714 set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5717 case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5719 set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5722 case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5724 set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5727 case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5729 set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5732 case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5734 set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5737 case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5739 set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5742 case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5744 set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5747 case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5749 set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5752 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5754 set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5757 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5759 set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5762 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5764 set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5767 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5769 set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5772 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5774 set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5777 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5779 set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5783 case VOGL_ENTRYPOINT_glUniform1f:
5785 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5788 case VOGL_ENTRYPOINT_glUniform1fARB:
5790 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5793 case VOGL_ENTRYPOINT_glUniform2f:
5795 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5798 case VOGL_ENTRYPOINT_glUniform2fARB:
5800 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5803 case VOGL_ENTRYPOINT_glUniform3f:
5805 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5808 case VOGL_ENTRYPOINT_glUniform3fARB:
5810 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5813 case VOGL_ENTRYPOINT_glUniform4f:
5815 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5818 case VOGL_ENTRYPOINT_glUniform4fARB:
5820 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5823 case VOGL_ENTRYPOINT_glUniform1i:
5825 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5828 case VOGL_ENTRYPOINT_glUniform1iARB:
5830 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5833 case VOGL_ENTRYPOINT_glUniform2i:
5835 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5838 case VOGL_ENTRYPOINT_glUniform2iARB:
5840 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5843 case VOGL_ENTRYPOINT_glUniform3i:
5845 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5848 case VOGL_ENTRYPOINT_glUniform3iARB:
5850 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5853 case VOGL_ENTRYPOINT_glUniform4i:
5855 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5858 case VOGL_ENTRYPOINT_glUniform4iARB:
5860 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5863 case VOGL_ENTRYPOINT_glUniform1ui:
5865 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5868 case VOGL_ENTRYPOINT_glUniform1uiEXT:
5870 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5873 case VOGL_ENTRYPOINT_glUniform2ui:
5875 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5878 case VOGL_ENTRYPOINT_glUniform2uiEXT:
5880 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5883 case VOGL_ENTRYPOINT_glUniform3ui:
5885 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5888 case VOGL_ENTRYPOINT_glUniform3uiEXT:
5890 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5893 case VOGL_ENTRYPOINT_glUniform4ui:
5895 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5898 case VOGL_ENTRYPOINT_glUniform4uiEXT:
5900 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5903 case VOGL_ENTRYPOINT_glUniform1uiv:
5905 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5908 case VOGL_ENTRYPOINT_glUniform1uivEXT:
5910 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5913 case VOGL_ENTRYPOINT_glUniform2uiv:
5915 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5918 case VOGL_ENTRYPOINT_glUniform2uivEXT:
5920 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5923 case VOGL_ENTRYPOINT_glUniform3uiv:
5925 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5928 case VOGL_ENTRYPOINT_glUniform3uivEXT:
5930 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5933 case VOGL_ENTRYPOINT_glUniform4uiv:
5935 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5938 case VOGL_ENTRYPOINT_glUniform4uivEXT:
5940 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5943 case VOGL_ENTRYPOINT_glUniform1iv:
5945 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5948 case VOGL_ENTRYPOINT_glUniform1ivARB:
5950 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5953 case VOGL_ENTRYPOINT_glUniform2iv:
5955 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5958 case VOGL_ENTRYPOINT_glUniform2ivARB:
5960 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5963 case VOGL_ENTRYPOINT_glUniform3iv:
5965 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5968 case VOGL_ENTRYPOINT_glUniform3ivARB:
5970 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5973 case VOGL_ENTRYPOINT_glUniform4iv:
5975 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5978 case VOGL_ENTRYPOINT_glUniform4ivARB:
5980 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5983 case VOGL_ENTRYPOINT_glUniform1fv:
5985 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5988 case VOGL_ENTRYPOINT_glUniform1fvARB:
5990 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5993 case VOGL_ENTRYPOINT_glUniform2fv:
5995 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5998 case VOGL_ENTRYPOINT_glUniform2fvARB:
6000 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
6003 case VOGL_ENTRYPOINT_glUniform3fv:
6005 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
6008 case VOGL_ENTRYPOINT_glUniform3fvARB:
6010 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
6013 case VOGL_ENTRYPOINT_glUniform4fv:
6015 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
6018 case VOGL_ENTRYPOINT_glUniform4fvARB:
6020 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
6023 case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
6025 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
6028 case VOGL_ENTRYPOINT_glUniformMatrix2fv:
6030 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
6033 case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
6035 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
6038 case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6040 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6043 case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6045 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6048 case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6050 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6053 case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6055 set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6058 case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6060 set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6063 case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6065 set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6068 case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6070 set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6073 case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6075 set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6078 case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6080 set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6083 case VOGL_ENTRYPOINT_glBeginQuery:
6084 case VOGL_ENTRYPOINT_glBeginQueryARB:
6086 GLenum target = trace_packet.get_param_value<GLenum>(0);
6087 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6088 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6090 if (!m_pCur_context_state->m_inside_gl_begin)
6093 if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6094 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6096 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6098 if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6100 if (check_gl_error())
6101 return cStatusGLError;
6103 get_shared_state()->m_query_targets[replay_handle] = target;
6108 case VOGL_ENTRYPOINT_glEndQuery:
6110 GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6113 case VOGL_ENTRYPOINT_glEndQueryARB:
6115 GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6118 case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6120 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6121 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6123 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6125 int n = g_gl_enums.get_pname_count(pname);
6128 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6129 return cStatusSoftFailure;
6133 vogl::growable_array<GLint, 16> params(n + 1);
6134 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6136 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6138 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6143 case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6145 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6146 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6148 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6150 int n = g_gl_enums.get_pname_count(pname);
6153 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6154 return cStatusSoftFailure;
6158 vogl::growable_array<GLint, 16> params(n + 1);
6159 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6161 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6163 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6168 case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6170 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6171 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6173 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6175 int n = g_gl_enums.get_pname_count(pname);
6178 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6179 return cStatusSoftFailure;
6183 vogl::growable_array<GLuint, 16> params(n + 1);
6184 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6186 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6188 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6193 case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6195 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6196 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6198 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6200 int n = g_gl_enums.get_pname_count(pname);
6203 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6204 return cStatusSoftFailure;
6208 vogl::growable_array<GLuint, 16> params(n + 1);
6209 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6211 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6213 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6218 case VOGL_ENTRYPOINT_glQueryCounter:
6220 VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6222 id = map_handle(get_shared_state()->m_queries, id);
6224 VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6228 case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6230 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6231 VOGL_NOTE_UNUSED(pTrace_params);
6233 id = map_handle(get_shared_state()->m_queries, id);
6235 int n = g_gl_enums.get_pname_count(pname);
6238 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6239 return cStatusSoftFailure;
6242 vogl::growable_array<GLint64, 16> temp_params(n + 1);
6243 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6245 GLint64 *pReplay_params = temp_params.get_ptr();
6247 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6249 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6253 case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6255 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6256 VOGL_NOTE_UNUSED(pTrace_params);
6258 id = map_handle(get_shared_state()->m_queries, id);
6260 int n = g_gl_enums.get_pname_count(pname);
6263 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6264 return cStatusSoftFailure;
6267 vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6268 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6270 GLuint64 *pReplay_params = temp_params.get_ptr();
6272 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6274 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6278 case VOGL_ENTRYPOINT_glBindBuffer:
6279 case VOGL_ENTRYPOINT_glBindBufferARB:
6281 GLenum target = trace_packet.get_param_value<GLenum>(0);
6282 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6283 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6287 SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6289 if (check_gl_error())
6290 return cStatusGLError;
6292 if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6294 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6296 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6297 else if (*pBinding == GL_NONE)
6303 case VOGL_ENTRYPOINT_glBindBufferBase:
6304 case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6305 case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6307 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6309 GLuint trace_buffer = buffer;
6310 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6314 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6315 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6316 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6317 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6319 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6321 if (check_gl_error())
6322 return cStatusGLError;
6324 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6326 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6328 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6329 else if (*pBinding == GL_NONE)
6335 case VOGL_ENTRYPOINT_glBindBufferRange:
6336 case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6337 case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6339 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6341 GLuint trace_buffer = buffer;
6342 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6346 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6347 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6348 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6349 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6351 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6353 if (check_gl_error())
6354 return cStatusGLError;
6356 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6358 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6360 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6361 else if (*pBinding == GL_NONE)
6367 case VOGL_ENTRYPOINT_glFenceSync:
6369 vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6372 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6375 process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6376 return cStatusHardFailure;
6380 get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6386 case VOGL_ENTRYPOINT_glWaitSync:
6387 case VOGL_ENTRYPOINT_glClientWaitSync:
6389 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6390 GLsync replay_sync = NULL;
6392 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6393 if (it == get_shared_state()->m_syncs.end())
6397 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6398 return cStatusHardFailure;
6403 replay_sync = it->second;
6406 if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6407 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6409 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6413 case VOGL_ENTRYPOINT_glDeleteSync:
6415 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6416 GLsync replay_sync = NULL;
6418 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6419 if (it == get_shared_state()->m_syncs.end())
6423 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6424 return cStatusHardFailure;
6429 replay_sync = it->second;
6432 GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6436 get_shared_state()->m_syncs.erase(trace_sync);
6441 case VOGL_ENTRYPOINT_glVertexPointer:
6443 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6444 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6447 case VOGL_ENTRYPOINT_glVertexPointerEXT:
6449 VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6450 VOGL_NOTE_UNUSED(pTrace_pointer);
6452 vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointerEXT), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6455 case VOGL_ENTRYPOINT_glColorPointer:
6457 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6458 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6461 case VOGL_ENTRYPOINT_glColorPointerEXT:
6463 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6464 VOGL_NOTE_UNUSED(pTrace_pointer);
6466 vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointerEXT), m_client_side_array_data[vogl_color_pointer_array_id]);
6469 case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6471 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6472 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6475 case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6477 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6478 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6481 case VOGL_ENTRYPOINT_glTexCoordPointer:
6483 GLint cur_client_active_texture = 0;
6484 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6486 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6487 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6489 process_entrypoint_error("%s: glTexCoordPointer/glTexCoordPointerEXT called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6490 return cStatusSoftFailure;
6493 vertex_array_helper(trace_packet.get_param_value<GLint>(0), trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLsizei>(2), trace_packet.get_param_ptr_value(3),
6494 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6497 case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6499 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6500 VOGL_NOTE_UNUSED(pTrace_pointer);
6502 GLint cur_client_active_texture = 0;
6503 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6505 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6506 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6508 process_entrypoint_error("%s: glTexCoordPointer/glTexCoordPointerEXT called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6509 return cStatusSoftFailure;
6512 vertex_array_helper_count(size, type, stride, count, trace_packet.get_param_ptr_value(4), vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointerEXT), m_client_side_texcoord_data[tex_index]);
6515 case VOGL_ENTRYPOINT_glFogCoordPointer:
6517 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6518 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6521 case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6523 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6524 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6527 case VOGL_ENTRYPOINT_glIndexPointer:
6529 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6530 vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6533 case VOGL_ENTRYPOINT_glIndexPointerEXT:
6535 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6536 VOGL_NOTE_UNUSED(pTrace_pointer);
6538 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6541 case VOGL_ENTRYPOINT_glNormalPointer:
6543 vertex_array_helper_no_size(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLsizei>(1), trace_packet.get_param_ptr_value(2),
6544 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6547 case VOGL_ENTRYPOINT_glNormalPointerEXT:
6549 VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6550 VOGL_NOTE_UNUSED(pTrace_pointer);
6552 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6555 case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6557 vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6558 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6561 case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6563 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6564 VOGL_NOTE_UNUSED(pTrace_pointer);
6566 vertex_array_helper_no_type_no_size_count(stride, count, trace_packet.get_param_ptr_value(2), vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointerEXT));
6569 case VOGL_ENTRYPOINT_glInterleavedArrays:
6571 // TODO: Test this more!
6572 GLenum format = trace_packet.get_param_value<GLenum>(0);
6573 GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6574 const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6577 for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6578 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6580 if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6582 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6583 return cStatusSoftFailure;
6588 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6589 return cStatusSoftFailure;
6592 const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6597 VOGL_ASSERT(stride > 0);
6600 GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6601 GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6602 GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6603 GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6609 GLint cur_client_active_texture = 0;
6610 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6612 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6613 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6615 process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6616 return cStatusSoftFailure;
6619 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6620 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6621 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6625 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6632 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6633 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6634 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6638 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6645 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6646 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6647 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6651 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6656 GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6657 vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6658 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6662 case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6663 case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6665 GLuint index = trace_packet.get_param_value<GLuint>(0);
6666 GLint size = trace_packet.get_param_value<GLint>(1);
6667 GLenum type = trace_packet.get_param_value<GLenum>(2);
6668 GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6669 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6671 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6673 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6674 return cStatusSoftFailure;
6677 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6678 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6679 if ((!buffer) && (trace_pointer))
6681 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6682 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6683 if (!m_client_side_vertex_attrib_data[index].size())
6685 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6687 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6690 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6691 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6693 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6697 case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6698 case VOGL_ENTRYPOINT_glVertexAttribPointer:
6700 GLuint index = trace_packet.get_param_value<GLuint>(0);
6701 GLint size = trace_packet.get_param_value<GLint>(1);
6702 GLenum type = trace_packet.get_param_value<GLenum>(2);
6703 GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6704 GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6705 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6707 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6709 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6710 return cStatusSoftFailure;
6713 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6714 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6715 if ((!buffer) && (trace_pointer))
6717 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6718 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6719 if (!m_client_side_vertex_attrib_data[index].size())
6721 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6723 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6726 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6727 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6729 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6733 case VOGL_ENTRYPOINT_glDrawRangeElements:
6734 case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6736 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6737 GLuint start = trace_packet.get_param_value<GLuint>(1);
6738 GLuint end = trace_packet.get_param_value<GLuint>(2);
6739 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6740 GLenum type = trace_packet.get_param_value<GLenum>(4);
6741 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6743 const GLvoid *pIndices;
6744 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6745 return cStatusSoftFailure;
6747 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6749 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6750 GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6752 GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6757 case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6759 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6760 GLuint start = trace_packet.get_param_value<GLuint>(1);
6761 GLuint end = trace_packet.get_param_value<GLuint>(2);
6762 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6763 GLenum type = trace_packet.get_param_value<GLenum>(4);
6764 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6765 GLint basevertex = trace_packet.get_param_value<GLint>(6);
6767 const GLvoid *pIndices;
6768 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6769 return cStatusSoftFailure;
6771 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6773 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6778 case VOGL_ENTRYPOINT_glDrawElements:
6780 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6781 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6782 GLenum type = trace_packet.get_param_value<GLenum>(2);
6783 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6785 const GLvoid *pIndices;
6786 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6787 return cStatusSoftFailure;
6789 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6791 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6796 case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6797 case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6799 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6801 const GLvoid *pIndices = NULL;
6802 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6803 return cStatusSoftFailure;
6805 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6807 GLsizei start = first, primcount = instancecount;
6808 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6811 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6815 case VOGL_ENTRYPOINT_glDrawArrays:
6816 case VOGL_ENTRYPOINT_glDrawArraysEXT:
6818 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6819 GLint first = trace_packet.get_param_value<GLint>(1);
6820 GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6822 const GLvoid *pIndices = NULL;
6823 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6824 return cStatusSoftFailure;
6826 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6828 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6829 GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6831 GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6836 case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6837 case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6838 case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6840 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6841 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6842 GLenum type = trace_packet.get_param_value<GLenum>(2);
6843 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6844 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6846 const GLvoid *pIndices;
6847 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6848 return cStatusSoftFailure;
6850 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6852 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6853 GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6854 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6855 GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6857 GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6862 case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6864 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6865 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6866 GLenum type = trace_packet.get_param_value<GLenum>(2);
6867 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6868 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6869 GLint basevertex = trace_packet.get_param_value<GLint>(5);
6871 const GLvoid *pIndices;
6872 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6873 return cStatusSoftFailure;
6875 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6877 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6882 case VOGL_ENTRYPOINT_glMultiDrawArrays:
6883 case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6885 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6887 const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6888 uint first_size = trace_packet.get_param_client_memory_data_size(1);
6890 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6891 uint count_size = trace_packet.get_param_client_memory_data_size(2);
6893 GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6895 if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6897 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6898 return cStatusSoftFailure;
6901 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6903 // Multi-draws with client side arrays are not supported for replay.
6904 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6905 GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6907 GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6912 case VOGL_ENTRYPOINT_glMultiDrawElements:
6913 case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6915 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6917 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6918 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6920 GLenum type = trace_packet.get_param_value<GLenum>(2);
6922 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6924 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6926 if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6928 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6929 return cStatusSoftFailure;
6932 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6933 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6934 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6936 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6938 // Multi-draws with client side arrays are not supported for replay.
6939 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6940 GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6942 GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6947 case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6949 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6951 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6952 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6954 GLenum type = trace_packet.get_param_value<GLenum>(2);
6956 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6957 //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6958 //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6960 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6962 const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6963 uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6965 if ((count_size != primcount * sizeof(GLsizei)) ||
6966 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6967 (base_vertex_size != primcount * sizeof(GLint)))
6969 process_entrypoint_error("%s: count, indices, and/or base_vertex_size params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6970 return cStatusSoftFailure;
6973 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6974 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6975 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6977 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6979 // Multi-draws with client side arrays are not supported for replay.
6980 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6985 case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6987 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6988 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6989 GLenum type = trace_packet.get_param_value<GLenum>(2);
6990 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6991 GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6993 const GLvoid *pIndices;
6994 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6995 return cStatusSoftFailure;
6997 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6999 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
7004 case VOGL_ENTRYPOINT_glGetBufferSubData:
7006 if (!benchmark_mode())
7008 GLenum target = trace_packet.get_param_value<GLenum>(0);
7009 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
7010 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
7011 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
7013 if (offset != static_cast<uintptr_t>(offset))
7015 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
7016 return cStatusHardFailure;
7019 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
7021 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
7022 return cStatusHardFailure;
7025 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
7027 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
7029 if ((buf.size()) && (pTrace_ptr))
7031 if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
7033 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7040 case VOGL_ENTRYPOINT_glGetClipPlane:
7042 if (!benchmark_mode())
7044 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7045 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7047 GLdouble equation[4];
7048 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7050 if (pTrace_equation)
7052 if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7054 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7061 case VOGL_ENTRYPOINT_glBufferData:
7062 case VOGL_ENTRYPOINT_glBufferDataARB:
7064 GLenum target = trace_packet.get_param_value<GLenum>(0);
7065 vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7066 const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7067 uint data_size = trace_packet.get_param_client_memory_data_size(2);
7068 GLenum usage = trace_packet.get_param_value<GLenum>(3);
7070 if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7072 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7073 return cStatusHardFailure;
7076 if (size != static_cast<uintptr_t>(size))
7078 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7079 return cStatusHardFailure;
7082 if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7083 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7085 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7087 GLuint buffer = vogl_get_bound_gl_buffer(target);
7090 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7093 for (i = 0; i < mapped_bufs.size(); i++)
7095 if (mapped_bufs[i].m_buffer == buffer)
7097 process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7099 mapped_bufs.erase_unordered(i);
7107 case VOGL_ENTRYPOINT_glMapBufferARB:
7108 case VOGL_ENTRYPOINT_glMapBuffer:
7110 GLenum target = trace_packet.get_param_value<GLenum>(0);
7111 GLenum access = trace_packet.get_param_value<GLenum>(1);
7112 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7114 // FIXME - must call GL even if !pTrace_result
7115 if (trace_result_ptr_value)
7118 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7119 pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7121 pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7125 process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7126 return cStatusHardFailure;
7129 GLuint buffer = vogl_get_bound_gl_buffer(target);
7131 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7134 for (i = 0; i < mapped_bufs.size(); i++)
7136 if (mapped_bufs[i].m_buffer == buffer)
7138 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7139 return cStatusHardFailure;
7143 if (i == mapped_bufs.size())
7146 GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7148 vogl_mapped_buffer_desc m;
7149 m.m_buffer = buffer;
7150 m.m_target = target;
7152 m.m_length = length;
7153 m.m_access = access;
7156 mapped_bufs.push_back(m);
7162 case VOGL_ENTRYPOINT_glMapBufferRange:
7164 GLenum target = trace_packet.get_param_value<GLenum>(0);
7165 vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7166 vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7167 GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7168 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7170 if (offset != static_cast<uintptr_t>(offset))
7172 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7173 return cStatusHardFailure;
7175 if (length != static_cast<uintptr_t>(length))
7177 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7178 return cStatusHardFailure;
7181 // FIXME - must call GL even if !pTrace_result
7182 if (trace_result_ptr_value)
7184 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7187 process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7188 return cStatusHardFailure;
7191 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7193 GLuint buffer = vogl_get_bound_gl_buffer(target);
7195 for (i = 0; i < mapped_bufs.size(); i++)
7197 if (mapped_bufs[i].m_buffer == buffer)
7199 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7200 return cStatusHardFailure;
7204 if (i == mapped_bufs.size())
7206 vogl_mapped_buffer_desc m;
7207 m.m_buffer = buffer;
7208 m.m_target = target;
7209 m.m_offset = offset;
7210 m.m_length = length;
7211 m.m_access = access;
7214 mapped_bufs.push_back(m);
7220 case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7222 // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7225 case VOGL_ENTRYPOINT_glUnmapBufferARB:
7226 case VOGL_ENTRYPOINT_glUnmapBuffer:
7228 GLenum target = trace_packet.get_param_value<GLenum>(0);
7229 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7231 GLuint buffer = vogl_get_bound_gl_buffer(target);
7233 // FIXME - must call GL even if !buffer
7236 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
7238 uint mapped_buffers_index;
7239 for (mapped_buffers_index = 0; mapped_buffers_index < mapped_bufs.size(); mapped_buffers_index++)
7240 if (mapped_bufs[mapped_buffers_index].m_buffer == buffer)
7242 if (mapped_buffers_index == mapped_bufs.size())
7244 process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7245 return cStatusHardFailure;
7248 vogl_mapped_buffer_desc &map_desc = mapped_bufs[mapped_buffers_index];
7250 bool writable_map = false;
7251 bool explicit_bit = false;
7252 if (map_desc.m_range)
7254 writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7255 explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7259 writable_map = (map_desc.m_access != GL_READ_ONLY);
7264 const key_value_map &unmap_data = trace_packet.get_key_value_map();
7268 int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7270 for (int i = 0; i < num_flushed_ranges; i++)
7272 int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7273 int64_t size = unmap_data.get_int64(i * 4 + 1);
7274 VOGL_NOTE_UNUSED(size);
7275 const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7278 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7279 return cStatusHardFailure;
7282 if (ofs != static_cast<GLintptr>(ofs))
7284 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7285 return cStatusHardFailure;
7288 VOGL_ASSERT(size == pData->size());
7290 memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7292 GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7297 int64_t ofs = unmap_data.get_int64(0);
7298 VOGL_NOTE_UNUSED(ofs);
7299 int64_t size = unmap_data.get_int64(1);
7300 VOGL_NOTE_UNUSED(size);
7301 const uint8_vec *pData = unmap_data.get_blob(2);
7304 process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7305 return cStatusHardFailure;
7309 memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7314 get_shared_state()->m_shadow_state.m_mapped_buffers.erase_unordered(mapped_buffers_index);
7317 GLboolean replay_result;
7318 if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7319 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7321 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7323 if (trace_result != replay_result)
7324 process_entrypoint_warning("%s: Replay glUnmapBuffer's return value differs from trace's (replay: %u vs. trace: %u)\n", VOGL_METHOD_NAME, replay_result, trace_result);
7328 case VOGL_ENTRYPOINT_glGenVertexArrays:
7330 if (!gen_handles(get_context_state()->m_vertex_array_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glGenVertexArrays), NULL))
7331 return cStatusHardFailure;
7334 case VOGL_ENTRYPOINT_glBindVertexArray:
7336 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7337 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7339 GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7342 case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7344 delete_handles(get_context_state()->m_vertex_array_objects, trace_packet.get_param_value<GLsizei>(0), static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)), GL_ENTRYPOINT(glDeleteVertexArrays));
7347 case VOGL_ENTRYPOINT_glIsFramebuffer:
7348 case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7350 if (!benchmark_mode())
7352 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7353 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7354 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7356 GLboolean replay_result;
7357 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7358 replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7360 replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7362 if (trace_result != replay_result)
7363 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7368 case VOGL_ENTRYPOINT_glIsBuffer:
7370 if (!benchmark_mode())
7372 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7373 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7374 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7376 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7377 if (trace_result != replay_result)
7378 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7382 case VOGL_ENTRYPOINT_glIsEnabledi:
7384 if (!benchmark_mode())
7386 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7387 GLuint index = trace_packet.get_param_value<GLuint>(1);
7388 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7390 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7391 if (trace_result != replay_result)
7392 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7396 case VOGL_ENTRYPOINT_glIsEnabled:
7398 if (!benchmark_mode())
7400 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7401 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7403 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7404 if (trace_result != replay_result)
7405 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7409 case VOGL_ENTRYPOINT_glIsProgram:
7411 if (!benchmark_mode())
7413 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7414 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7415 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7417 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7419 if (trace_result != replay_result)
7420 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7424 case VOGL_ENTRYPOINT_glIsQuery:
7426 if (!benchmark_mode())
7428 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7429 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7430 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7432 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7433 if (trace_result != replay_result)
7434 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7438 case VOGL_ENTRYPOINT_glIsShader:
7440 if (!benchmark_mode())
7442 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7443 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7444 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7446 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7447 if (trace_result != replay_result)
7448 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7452 case VOGL_ENTRYPOINT_glIsTexture:
7453 case VOGL_ENTRYPOINT_glIsTextureEXT:
7455 if (!benchmark_mode())
7457 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7458 GLuint replay_handle = trace_handle;
7459 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7461 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7463 GLboolean replay_result;
7464 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7465 replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7467 replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7469 if (trace_result != replay_result)
7470 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7475 case VOGL_ENTRYPOINT_glIsVertexArray:
7477 if (!benchmark_mode())
7479 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7480 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7481 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7483 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7484 if (trace_result != replay_result)
7485 process_entrypoint_error("%s: Replay's returned GLboolean differed from trace's! Replay: %u Trace: %u\n", VOGL_METHOD_NAME, static_cast<uint>(replay_result), static_cast<uint>(trace_result));
7490 case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7492 if (!benchmark_mode())
7494 GLenum target = trace_packet.get_param_value<GLenum>(0);
7495 GLint level = trace_packet.get_param_value<GLint>(1);
7496 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7497 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7498 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7500 int n = g_gl_enums.get_pname_count(pname);
7503 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7504 return cStatusSoftFailure;
7507 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7508 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7510 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7512 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7515 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7516 else if (trace_params_size != sizeof(GLfloat) * n)
7517 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7518 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7519 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7524 case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7526 if (!benchmark_mode())
7528 GLenum target = trace_packet.get_param_value<GLenum>(0);
7529 GLint level = trace_packet.get_param_value<GLint>(1);
7530 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7531 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7532 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7534 int n = g_gl_enums.get_pname_count(pname);
7537 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7538 return cStatusSoftFailure;
7541 vogl::growable_array<GLint, 16> replay_params(n + 1);
7542 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7544 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7546 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7549 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7550 else if (trace_params_size != sizeof(GLint) * n)
7551 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7552 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7553 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7558 case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7559 case VOGL_ENTRYPOINT_glGetTexParameteriv:
7561 if (!benchmark_mode())
7563 GLenum target = trace_packet.get_param_value<GLenum>(0);
7564 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7565 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7566 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7568 int n = g_gl_enums.get_pname_count(pname);
7571 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7572 return cStatusSoftFailure;
7575 vogl::growable_array<GLint, 16> replay_params(n + 1);
7576 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7578 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7579 GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7581 GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7583 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7586 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7587 else if (trace_params_size != sizeof(GLint) * n)
7588 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7589 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7590 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7595 case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7597 if (!benchmark_mode())
7599 GLenum target = trace_packet.get_param_value<GLenum>(0);
7600 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7601 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7602 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7604 int n = g_gl_enums.get_pname_count(pname);
7607 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7608 return cStatusSoftFailure;
7611 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7612 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7614 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7616 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7619 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7620 else if (trace_params_size != sizeof(GLuint) * n)
7621 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7622 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7623 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7628 case VOGL_ENTRYPOINT_glGetTexParameterfv:
7630 if (!benchmark_mode())
7632 GLenum target = trace_packet.get_param_value<GLenum>(0);
7633 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7634 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7635 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7637 int n = g_gl_enums.get_pname_count(pname);
7640 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7641 return cStatusSoftFailure;
7644 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7645 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7647 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7649 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7652 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7653 else if (trace_params_size != sizeof(GLfloat) * n)
7654 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7655 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7656 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7662 case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7664 status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7665 if (status != cStatusOK)
7669 case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7671 status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7672 if (status != cStatusOK)
7676 case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7678 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7679 if (status != cStatusOK)
7683 case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7685 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7686 if (status != cStatusOK)
7690 case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7692 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7693 if (status != cStatusOK)
7697 case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7699 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7700 if (status != cStatusOK)
7704 case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7706 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7707 if (status != cStatusOK)
7711 case VOGL_ENTRYPOINT_glGenLists:
7713 GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7714 GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7716 if (trace_base_handle)
7720 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7722 if ((check_gl_error()) || (!replay_base_handle))
7724 process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7725 return cStatusHardFailure;
7728 for (GLsizei i = 0; i < range; i++)
7730 GLuint trace_handle = trace_base_handle + i;
7731 GLuint replay_handle = replay_base_handle + i;
7733 if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7734 return cStatusHardFailure;
7736 if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7738 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);
7744 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7745 if (replay_base_handle)
7747 process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7749 GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7755 case VOGL_ENTRYPOINT_glCallList:
7757 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7758 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7760 GL_ENTRYPOINT(glCallList)(replay_handle);
7762 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7764 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7767 if ((status = post_draw_call()) != cStatusOK)
7772 case VOGL_ENTRYPOINT_glCallLists:
7774 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7775 GLenum type = trace_packet.get_param_value<GLenum>(1);
7776 const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7777 uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7779 uint type_size = vogl_get_gl_type_size(type);
7782 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7783 return cStatusSoftFailure;
7786 if ((n) && (!pTrace_lists))
7788 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7789 return cStatusSoftFailure;
7792 if (trace_lists_size < (type_size * n))
7794 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7795 return cStatusSoftFailure;
7798 GLuint list_base = 0;
7799 GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7801 const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7802 for (GLsizei i = 0; i < n; i++)
7804 GLint trace_handle = list_base;
7809 trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7813 case GL_UNSIGNED_BYTE:
7815 trace_handle += *pTrace_lists_ptr;
7821 trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7822 pTrace_lists_ptr += sizeof(int16);
7825 case GL_UNSIGNED_SHORT:
7827 trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7828 pTrace_lists_ptr += sizeof(uint16);
7833 trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7834 pTrace_lists_ptr += sizeof(int32);
7837 case GL_UNSIGNED_INT:
7839 trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7840 pTrace_lists_ptr += sizeof(uint32);
7845 trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7846 pTrace_lists_ptr += sizeof(float);
7851 trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7852 pTrace_lists_ptr += 2;
7857 trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7858 pTrace_lists_ptr += 3;
7863 trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7864 pTrace_lists_ptr += 4;
7869 process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7870 return cStatusSoftFailure;
7874 if (trace_handle <= 0)
7876 process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7880 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7881 GL_ENTRYPOINT(glCallList)(replay_handle);
7883 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7885 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7890 if ((status = post_draw_call()) != cStatusOK)
7895 case VOGL_ENTRYPOINT_glDeleteLists:
7897 GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7898 GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7900 for (GLsizei i = 0; i < range; i++)
7902 GLuint trace_handle = trace_list + i;
7903 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7905 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7907 process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7913 case VOGL_ENTRYPOINT_glIsList:
7915 if (!benchmark_mode())
7917 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7918 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7919 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7921 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7922 if (trace_result != replay_result)
7923 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));
7928 case VOGL_ENTRYPOINT_glNewList:
7930 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7931 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7932 GLenum mode = trace_packet.get_param_value<GLenum>(1);
7936 GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7938 if (!check_gl_error())
7940 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7942 get_context_state()->m_current_display_list_mode = mode;
7943 get_context_state()->m_current_display_list_handle = trace_handle;
7946 // TODO: Check if glNewList() failed vs the replay.
7947 // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7948 // 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.
7951 case VOGL_ENTRYPOINT_glListBase:
7953 GLuint base = trace_packet.get_param_value<GLuint>(0);
7954 GL_ENTRYPOINT(glListBase)(base);
7957 case VOGL_ENTRYPOINT_glEndList:
7959 GL_ENTRYPOINT(glEndList)();
7961 if (!get_context_state()->is_composing_display_list())
7963 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7967 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7968 process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7970 get_context_state()->m_current_display_list_mode = GL_NONE;
7971 get_context_state()->m_current_display_list_handle = -1;
7976 case VOGL_ENTRYPOINT_glFeedbackBuffer:
7978 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7979 GLenum type = trace_packet.get_param_value<GLenum>(1);
7981 if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
7982 m_pCur_context_state->m_feedback_buffer.resize(size);
7984 GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
7988 case VOGL_ENTRYPOINT_glSeparableFilter2D:
7990 GLenum target = trace_packet.get_param_value<GLenum>(0);
7991 GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
7992 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7993 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7994 GLenum format = trace_packet.get_param_value<GLenum>(4);
7995 GLenum type = trace_packet.get_param_value<GLenum>(5);
7997 const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
7998 uint row_size = trace_packet.get_param_client_memory_data_size(6);
7999 if (row_size < vogl_get_image_size(format, type, width, 1, 1))
8001 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8002 return cStatusSoftFailure;
8005 const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8006 uint col_size = trace_packet.get_param_client_memory_data_size(7);
8007 if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8009 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8010 return cStatusSoftFailure;
8013 GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8017 case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8019 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8020 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8022 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));
8026 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8028 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8029 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8031 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));
8034 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8036 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8037 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8039 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));
8043 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8045 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8046 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8048 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));
8051 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8053 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8054 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8056 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8057 trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8058 trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8061 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8063 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8064 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8066 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));
8069 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8071 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8072 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8074 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));
8077 case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8079 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8080 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8082 GL_ENTRYPOINT(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));
8085 case VOGL_ENTRYPOINT_glGetTexEnvfv:
8087 if (!benchmark_mode())
8089 GLenum target = trace_packet.get_param_value<GLenum>(0);
8090 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8091 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8093 GLfloat vals[4] = { 0, 0, 0, 0 };
8095 int n = g_gl_enums.get_pname_count(pname);
8096 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8098 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8102 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8104 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8106 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8112 case VOGL_ENTRYPOINT_glGetTexEnviv:
8114 if (!benchmark_mode())
8116 GLenum target = trace_packet.get_param_value<GLenum>(0);
8117 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8118 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8120 GLint vals[4] = { 0, 0, 0, 0 };
8122 int n = g_gl_enums.get_pname_count(pname);
8123 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8125 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8129 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8131 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8133 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8139 case VOGL_ENTRYPOINT_glGetTexGendv:
8141 if (!benchmark_mode())
8143 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8144 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8145 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8147 GLdouble vals[4] = { 0, 0, 0, 0 };
8149 int n = g_gl_enums.get_pname_count(pname);
8150 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8152 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8156 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8158 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8160 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8166 case VOGL_ENTRYPOINT_glGetTexGenfv:
8168 if (!benchmark_mode())
8170 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8171 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8172 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8174 GLfloat vals[4] = { 0, 0, 0, 0 };
8176 int n = g_gl_enums.get_pname_count(pname);
8177 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8179 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8183 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8185 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8187 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8193 case VOGL_ENTRYPOINT_glGetTexGeniv:
8195 if (!benchmark_mode())
8197 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8198 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8199 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8201 GLint vals[4] = { 0, 0, 0, 0 };
8203 int n = g_gl_enums.get_pname_count(pname);
8204 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8206 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8210 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8212 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8214 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8220 case VOGL_ENTRYPOINT_glGetLightfv:
8222 if (!benchmark_mode())
8224 GLenum light = trace_packet.get_param_value<GLenum>(0);
8225 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8226 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8228 GLfloat vals[4] = { 0, 0, 0, 0 };
8230 int n = g_gl_enums.get_pname_count(pname);
8231 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8233 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8237 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8239 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8241 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8247 case VOGL_ENTRYPOINT_glGetLightiv:
8249 if (!benchmark_mode())
8251 GLenum light = trace_packet.get_param_value<GLenum>(0);
8252 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8253 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8255 GLint vals[4] = { 0, 0, 0, 0 };
8257 int n = g_gl_enums.get_pname_count(pname);
8258 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8260 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8264 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8266 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8268 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8274 case VOGL_ENTRYPOINT_glSelectBuffer:
8276 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8278 if (m_pCur_context_state->m_select_buffer.try_resize(size))
8280 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8284 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8289 case VOGL_ENTRYPOINT_glClearBufferfv:
8291 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8293 // TODO: Check params
8295 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8299 case VOGL_ENTRYPOINT_glClearBufferiv:
8301 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8303 // TODO: Check params
8305 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8309 case VOGL_ENTRYPOINT_glClearBufferuiv:
8311 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8313 // TODO: Check params
8315 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8319 case VOGL_ENTRYPOINT_glTexBuffer:
8320 case VOGL_ENTRYPOINT_glTexBufferARB:
8321 case VOGL_ENTRYPOINT_glTexBufferEXT:
8323 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8325 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8327 SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8330 case VOGL_ENTRYPOINT_glBeginConditionalRender:
8332 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8334 id = map_handle(get_shared_state()->m_queries, id);
8336 VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8339 case VOGL_ENTRYPOINT_glEndConditionalRender:
8341 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8343 VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8346 case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8348 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8350 VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8353 case VOGL_ENTRYPOINT_glEndTransformFeedback:
8355 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8357 VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8361 case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8363 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8364 VOGL_NOTE_UNUSED(pTrace_varyings);
8366 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8368 dynamic_string_array replay_varyings(count);
8370 const key_value_map &key_value_map = trace_packet.get_key_value_map();
8371 const value_to_value_hash_map &hash_map = key_value_map.get_map();
8373 for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8375 int key_index = it->first.get_int();
8377 if ((key_index >= 0) && (key_index < count))
8379 const dynamic_string *pName = it->second.get_string_ptr();
8382 replay_varyings[key_index] = pName ? *pName : "";
8390 vogl::vector<const GLchar *> str_ptrs(count);
8391 for (int i = 0; i < count; i++)
8392 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8394 GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8396 VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8400 case VOGL_ENTRYPOINT_glUniformBufferEXT:
8402 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8404 GLuint trace_program = program;
8406 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8407 location = determine_uniform_replay_location(trace_program, location);
8408 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8410 VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8413 case VOGL_ENTRYPOINT_glUniformBlockBinding:
8415 // TODO: Does any of this other stuff need to be remapped?
8416 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8418 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8420 VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8423 case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8425 // TODO - we need to hook up this extension to the tracer
8428 case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8430 // TODO - we need to hook up this extension to the tracer
8433 case VOGL_ENTRYPOINT_glBitmap:
8435 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBitmap;
8437 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8439 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8440 pTrace_bitmap = (const GLubyte *)ptr_val;
8443 VOGL_REPLAY_CALL_GL_HELPER_glBitmap;
8447 case VOGL_ENTRYPOINT_glColorSubTable:
8449 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTable;
8451 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8453 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8454 pTrace_data = (const GLvoid *)ptr_val;
8457 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTable;
8461 case VOGL_ENTRYPOINT_glColorSubTableEXT:
8463 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorSubTableEXT;
8465 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8467 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8468 pTrace_data = (const GLvoid *)ptr_val;
8471 VOGL_REPLAY_CALL_GL_HELPER_glColorSubTableEXT;
8475 case VOGL_ENTRYPOINT_glColorTable:
8477 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTable;
8479 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8481 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8482 pTrace_table = (const GLvoid *)ptr_val;
8485 VOGL_REPLAY_CALL_GL_HELPER_glColorTable;
8489 case VOGL_ENTRYPOINT_glColorTableEXT:
8491 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorTableEXT;
8493 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8495 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8496 pTrace_table = (const GLvoid *)ptr_val;
8499 VOGL_REPLAY_CALL_GL_HELPER_glColorTableEXT;
8503 case VOGL_ENTRYPOINT_glConvolutionFilter1D:
8505 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter1D;
8507 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8509 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(5);
8510 pTrace_image = (const GLvoid *)ptr_val;
8513 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter1D;
8517 case VOGL_ENTRYPOINT_glConvolutionFilter2D:
8519 VOGL_REPLAY_LOAD_PARAMS_HELPER_glConvolutionFilter2D;
8521 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8523 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8524 pTrace_image = (const GLvoid *)ptr_val;
8527 VOGL_REPLAY_CALL_GL_HELPER_glConvolutionFilter2D;
8531 case VOGL_ENTRYPOINT_glDrawPixels:
8533 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawPixels;
8535 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8537 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(4);
8538 pTrace_pixels = (const GLvoid *)ptr_val;
8541 VOGL_REPLAY_CALL_GL_HELPER_glDrawPixels;
8545 case VOGL_ENTRYPOINT_glPolygonStipple:
8547 VOGL_REPLAY_LOAD_PARAMS_HELPER_glPolygonStipple;
8549 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8551 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(0);
8552 pTrace_mask = (const GLubyte *)ptr_val;
8555 VOGL_REPLAY_CALL_GL_HELPER_glPolygonStipple;
8559 case VOGL_ENTRYPOINT_glTexImage1D:
8561 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage1D;
8563 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8565 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(7);
8566 pTrace_pixels = (const GLvoid *)ptr_val;
8569 VOGL_REPLAY_CALL_GL_HELPER_glTexImage1D;
8573 case VOGL_ENTRYPOINT_glTexImage2D:
8575 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage2D;
8577 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8579 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8580 pTrace_pixels = (const GLvoid *)ptr_val;
8583 VOGL_REPLAY_CALL_GL_HELPER_glTexImage2D;
8587 case VOGL_ENTRYPOINT_glTexImage3D:
8589 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3D;
8591 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8593 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8594 pTrace_pixels = (const GLvoid *)ptr_val;
8597 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3D;
8601 case VOGL_ENTRYPOINT_glTexImage3DEXT:
8603 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexImage3DEXT;
8605 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8607 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(9);
8608 pTrace_pixels = (const GLvoid *)ptr_val;
8611 VOGL_REPLAY_CALL_GL_HELPER_glTexImage3DEXT;
8615 case VOGL_ENTRYPOINT_glTexSubImage1D:
8617 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1D;
8619 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8621 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8622 pTrace_pixels = (const GLvoid *)ptr_val;
8625 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1D;
8629 case VOGL_ENTRYPOINT_glTexSubImage1DEXT:
8631 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage1DEXT;
8633 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8635 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(6);
8636 pTrace_pixels = (const GLvoid *)ptr_val;
8639 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage1DEXT;
8643 case VOGL_ENTRYPOINT_glTexSubImage2D:
8645 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2D;
8647 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8649 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8650 pTrace_pixels = (const GLvoid *)ptr_val;
8653 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2D;
8657 case VOGL_ENTRYPOINT_glTexSubImage2DEXT:
8659 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage2DEXT;
8661 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8663 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(8);
8664 pTrace_pixels = (const GLvoid *)ptr_val;
8667 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage2DEXT;
8671 case VOGL_ENTRYPOINT_glTexSubImage3D:
8673 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3D;
8675 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8677 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8678 pTrace_pixels = (const GLvoid *)ptr_val;
8681 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3D;
8685 case VOGL_ENTRYPOINT_glTexSubImage3DEXT:
8687 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexSubImage3DEXT;
8689 if (vogl_get_bound_gl_buffer(GL_PIXEL_UNPACK_BUFFER))
8691 vogl_trace_ptr_value ptr_val = trace_packet.get_param_ptr_value(10);
8692 pTrace_pixels = (const GLvoid *)ptr_val;
8695 VOGL_REPLAY_CALL_GL_HELPER_glTexSubImage3DEXT;
8699 case VOGL_ENTRYPOINT_glDebugMessageInsert:
8701 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDebugMessageInsert;
8703 VOGL_REPLAY_CALL_GL_HELPER_glDebugMessageInsert;
8706 case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8708 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDebugMessageInsertARB;
8710 VOGL_REPLAY_CALL_GL_HELPER_glDebugMessageInsertARB;
8713 case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8715 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
8719 case VOGL_ENTRYPOINT_glDebugMessageCallback:
8721 GL_ENTRYPOINT(glDebugMessageCallback)(debug_callback, (GLvoid *)m_pCur_context_state);
8725 case VOGL_ENTRYPOINT_glObjectLabel:
8727 VOGL_REPLAY_LOAD_PARAMS_HELPER_glObjectLabel;
8733 name = map_handle(get_shared_state()->m_buffers, name);
8739 name = map_handle(get_shared_state()->m_shadow_state.m_objs, name);
8742 case GL_VERTEX_ARRAY:
8744 name = map_handle(get_shared_state()->m_vertex_array_objects, name);
8749 name = map_handle(get_shared_state()->m_queries, name);
8754 name = map_handle(get_shared_state()->m_sampler_objects, name);
8759 name = map_handle(get_shared_state()->m_shadow_state.m_textures, name);
8762 case GL_RENDERBUFFER:
8764 name = map_handle(get_shared_state()->m_shadow_state.m_rbos, name);
8767 case GL_FRAMEBUFFER:
8769 name = map_handle(get_shared_state()->m_framebuffers, name);
8772 case GL_DISPLAY_LIST:
8774 name = map_handle(get_shared_state()->m_lists, name);
8777 case GL_TRANSFORM_FEEDBACK: // TODO: Investigate this more
8778 case GL_PROGRAM_PIPELINE: // TODO: We don't support program pipelines yet
8781 process_entrypoint_error("%s: Unsupported object identifier 0x%X\n", VOGL_METHOD_NAME, identifier);
8782 return cStatusSoftFailure;
8786 VOGL_REPLAY_CALL_GL_HELPER_glObjectLabel;
8790 case VOGL_ENTRYPOINT_glObjectPtrLabel:
8792 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
8793 GLsizei length = trace_packet.get_param_value<GLsizei>(1);
8794 const GLchar *pTrace_label = reinterpret_cast<const GLchar *>(trace_packet.get_param_client_memory_ptr(2));
8795 GLsync replay_sync = NULL;
8799 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
8800 if (it == get_shared_state()->m_syncs.end())
8802 process_entrypoint_error("%s: Failed remapping trace sync value 0x%" PRIx64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(trace_sync));
8803 return cStatusSoftFailure;
8807 replay_sync = it->second;
8811 GL_ENTRYPOINT(glObjectPtrLabel)(replay_sync, length, pTrace_label);
8815 case VOGL_ENTRYPOINT_glReadPixels:
8817 GLint x = trace_packet.get_param_value<GLint>(0);
8818 GLint y = trace_packet.get_param_value<GLint>(1);
8819 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
8820 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
8821 GLenum format = trace_packet.get_param_value<GLenum>(4);
8822 GLenum type = trace_packet.get_param_value<GLenum>(5);
8824 GLuint pixel_pack_buf = vogl_get_bound_gl_buffer(GL_PIXEL_PACK_BUFFER);
8827 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, reinterpret_cast<GLvoid *>(trace_packet.get_param_ptr_value(6)));
8831 const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
8832 uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
8834 size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
8835 if (replay_data_size != trace_data_size)
8837 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
8839 else if (!trace_data)
8841 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
8844 if (replay_data_size > cUINT32_MAX)
8846 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
8847 return cStatusHardFailure;
8850 vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
8851 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
8853 if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
8855 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
8857 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
8862 process_entrypoint_warning("%s: Replay's computed glReadPixels image size differs from traces (%u vs %u)!\n", VOGL_METHOD_NAME, static_cast<uint>(trace_data_size), static_cast<uint>(replay_data_size));
8868 case VOGL_ENTRYPOINT_glGetTexImage:
8870 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetTexImage;
8872 GLuint pixel_pack_buf = vogl_get_bound_gl_buffer(GL_PIXEL_PACK_BUFFER);
8875 GLvoid *pReplay_pixels = reinterpret_cast<GLvoid *>(trace_packet.get_param_ptr_value(4));
8877 VOGL_REPLAY_CALL_GL_HELPER_glGetTexImage;
8881 uint trace_data_size = trace_packet.get_param_client_memory_data_size(4);
8883 size_t replay_data_size = vogl_get_tex_target_image_size(target, level, format, type);
8885 if (replay_data_size > cUINT32_MAX)
8887 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
8888 return cStatusHardFailure;
8891 uint8_vec data(static_cast<uint>(replay_data_size));
8893 GLvoid *pReplay_pixels = data.get_ptr();
8895 VOGL_REPLAY_CALL_GL_HELPER_glGetTexImage;
8897 if ((trace_data_size == replay_data_size) && (trace_data_size) && (pTrace_pixels))
8899 if (memcmp(data.get_ptr(), pTrace_pixels, trace_data_size) != 0)
8901 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
8906 process_entrypoint_warning("%s: Replay's computed glGetTexImage() image size differs from traces (%u vs %u)!\n", VOGL_METHOD_NAME, static_cast<uint>(trace_data_size), static_cast<uint>(replay_data_size));
8912 case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8914 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetCompressedTexImage
8916 VOGL_NOTE_UNUSED(pTrace_img);
8918 GLuint pixel_pack_buf = vogl_get_bound_gl_buffer(GL_PIXEL_PACK_BUFFER);
8921 GLvoid *pReplay_img = reinterpret_cast<GLvoid *>(trace_packet.get_param_ptr_value(2));
8923 VOGL_REPLAY_CALL_GL_HELPER_glGetCompressedTexImage;
8927 // TODO: Implement non-pixel pack buffer path, compare for divergence
8932 case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8933 case VOGL_ENTRYPOINT_glGetObjectLabel:
8934 case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8935 case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8936 case VOGL_ENTRYPOINT_glAreTexturesResident:
8937 case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8938 case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8939 case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8940 case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8941 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8942 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8943 case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8944 case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8945 case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8946 case VOGL_ENTRYPOINT_glGetActiveUniformName:
8947 case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8948 case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8949 case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8950 case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8951 case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8952 case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8953 case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8954 case VOGL_ENTRYPOINT_glGetBooleani_v:
8955 case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8956 case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8957 case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8958 case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8959 case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8960 case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8961 case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8962 case VOGL_ENTRYPOINT_glGetColorTable:
8963 case VOGL_ENTRYPOINT_glGetColorTableEXT:
8964 case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8965 case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8966 case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8967 case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8968 case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8969 case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8970 case VOGL_ENTRYPOINT_glGetColorTableSGI:
8971 case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8972 case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8973 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8974 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8975 case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8976 case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8977 case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8978 case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8979 case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8980 case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8981 case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8982 case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8983 case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8984 case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8985 case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8986 case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8987 case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8988 case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8989 case VOGL_ENTRYPOINT_glGetDoublei_v:
8990 case VOGL_ENTRYPOINT_glGetFenceivNV:
8991 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8992 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8993 case VOGL_ENTRYPOINT_glGetFixedvOES:
8994 case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8995 case VOGL_ENTRYPOINT_glGetFloati_v:
8996 case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8997 case VOGL_ENTRYPOINT_glGetFragDataIndex:
8998 case VOGL_ENTRYPOINT_glGetFragDataLocation:
8999 case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
9000 case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
9001 case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
9002 case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
9003 case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
9004 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
9005 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
9006 case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
9007 case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
9008 case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
9009 case VOGL_ENTRYPOINT_glGetHandleARB:
9010 case VOGL_ENTRYPOINT_glGetHistogram:
9011 case VOGL_ENTRYPOINT_glGetHistogramEXT:
9012 case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
9013 case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
9014 case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
9015 case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
9016 case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
9017 case VOGL_ENTRYPOINT_glGetImageHandleNV:
9018 case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
9019 case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
9020 case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
9021 case VOGL_ENTRYPOINT_glGetInteger64i_v:
9022 case VOGL_ENTRYPOINT_glGetInteger64v:
9023 case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
9024 case VOGL_ENTRYPOINT_glGetIntegeri_v:
9025 case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
9026 case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
9027 case VOGL_ENTRYPOINT_glGetInternalformati64v:
9028 case VOGL_ENTRYPOINT_glGetInternalformativ:
9029 case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
9030 case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
9031 case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
9032 case VOGL_ENTRYPOINT_glGetLightxOES:
9033 case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
9034 case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
9035 case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
9036 case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
9037 case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
9038 case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
9039 case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
9040 case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
9041 case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
9042 case VOGL_ENTRYPOINT_glGetMapParameterivNV:
9043 case VOGL_ENTRYPOINT_glGetMapdv:
9044 case VOGL_ENTRYPOINT_glGetMapfv:
9045 case VOGL_ENTRYPOINT_glGetMapiv:
9046 case VOGL_ENTRYPOINT_glGetMapxvOES:
9047 case VOGL_ENTRYPOINT_glGetMaterialfv:
9048 case VOGL_ENTRYPOINT_glGetMaterialiv:
9049 case VOGL_ENTRYPOINT_glGetMaterialxOES:
9050 case VOGL_ENTRYPOINT_glGetMinmax:
9051 case VOGL_ENTRYPOINT_glGetMinmaxEXT:
9052 case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
9053 case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
9054 case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
9055 case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
9056 case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
9057 case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
9058 case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
9059 case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
9060 case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
9061 case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
9062 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
9063 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
9064 case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
9065 case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
9066 case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
9067 case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
9068 case VOGL_ENTRYPOINT_glGetMultisamplefv:
9069 case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
9070 case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
9071 case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
9072 case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
9073 case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
9074 case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
9075 case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
9076 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
9077 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
9078 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
9079 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
9080 case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
9081 case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
9082 case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
9083 case VOGL_ENTRYPOINT_glGetNamedStringARB:
9084 case VOGL_ENTRYPOINT_glGetNamedStringivARB:
9085 case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
9086 case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
9087 case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
9088 case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
9089 case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
9090 case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
9091 case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
9092 case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
9093 case VOGL_ENTRYPOINT_glGetPathCommandsNV:
9094 case VOGL_ENTRYPOINT_glGetPathCoordsNV:
9095 case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
9096 case VOGL_ENTRYPOINT_glGetPathLengthNV:
9097 case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
9098 case VOGL_ENTRYPOINT_glGetPathMetricsNV:
9099 case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
9100 case VOGL_ENTRYPOINT_glGetPathParameterivNV:
9101 case VOGL_ENTRYPOINT_glGetPathSpacingNV:
9102 case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
9103 case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
9104 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
9105 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
9106 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
9107 case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
9108 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
9109 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
9110 case VOGL_ENTRYPOINT_glGetPixelMapfv:
9111 case VOGL_ENTRYPOINT_glGetPixelMapuiv:
9112 case VOGL_ENTRYPOINT_glGetPixelMapusv:
9113 case VOGL_ENTRYPOINT_glGetPixelMapxv:
9114 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
9115 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
9116 case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
9117 case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
9118 case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
9119 case VOGL_ENTRYPOINT_glGetPointervEXT:
9120 case VOGL_ENTRYPOINT_glGetPolygonStipple:
9121 case VOGL_ENTRYPOINT_glGetProgramBinary:
9122 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
9123 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
9124 case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
9125 case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
9126 case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
9127 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
9128 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
9129 case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
9130 case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
9131 case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
9132 case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
9133 case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
9134 case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
9135 case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
9136 case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
9137 case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
9138 case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
9139 case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
9140 case VOGL_ENTRYPOINT_glGetProgramResourceName:
9141 case VOGL_ENTRYPOINT_glGetProgramResourceiv:
9142 case VOGL_ENTRYPOINT_glGetProgramStageiv:
9143 case VOGL_ENTRYPOINT_glGetProgramStringARB:
9144 case VOGL_ENTRYPOINT_glGetProgramStringNV:
9145 case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
9146 case VOGL_ENTRYPOINT_glGetProgramivNV:
9147 case VOGL_ENTRYPOINT_glGetQueryIndexediv:
9148 case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
9149 case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
9150 case VOGL_ENTRYPOINT_glGetQueryiv:
9151 case VOGL_ENTRYPOINT_glGetQueryivARB:
9152 case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
9153 case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
9154 case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
9155 case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
9156 case VOGL_ENTRYPOINT_glGetSeparableFilter:
9157 case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
9158 case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
9159 case VOGL_ENTRYPOINT_glGetShaderSource:
9160 case VOGL_ENTRYPOINT_glGetShaderSourceARB:
9161 case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
9162 case VOGL_ENTRYPOINT_glGetSubroutineIndex:
9163 case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
9164 case VOGL_ENTRYPOINT_glGetSynciv:
9165 case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
9166 case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
9167 case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
9168 case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
9169 case VOGL_ENTRYPOINT_glGetTexGenxvOES:
9170 case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
9171 case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
9172 case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
9173 case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
9174 case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
9175 case VOGL_ENTRYPOINT_glGetTextureHandleNV:
9176 case VOGL_ENTRYPOINT_glGetTextureImageEXT:
9177 case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
9178 case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
9179 case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
9180 case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
9181 case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
9182 case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
9183 case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
9184 case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
9185 case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
9186 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
9187 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
9188 case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
9189 case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
9190 case VOGL_ENTRYPOINT_glGetUniformIndices:
9191 case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
9192 case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
9193 case VOGL_ENTRYPOINT_glGetUniformdv:
9194 case VOGL_ENTRYPOINT_glGetUniformfv:
9195 case VOGL_ENTRYPOINT_glGetUniformfvARB:
9196 case VOGL_ENTRYPOINT_glGetUniformi64vNV:
9197 case VOGL_ENTRYPOINT_glGetUniformiv:
9198 case VOGL_ENTRYPOINT_glGetUniformivARB:
9199 case VOGL_ENTRYPOINT_glGetUniformui64vNV:
9200 case VOGL_ENTRYPOINT_glGetUniformuiv:
9201 case VOGL_ENTRYPOINT_glGetUniformuivEXT:
9202 case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
9203 case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
9204 case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
9205 case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
9206 case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
9207 case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
9208 case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
9209 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
9210 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
9211 case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
9212 case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
9213 case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
9214 case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
9215 case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
9216 case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
9217 case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
9218 case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
9219 case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
9220 case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
9221 case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
9222 case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
9223 case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
9224 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
9225 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
9226 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
9227 case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
9228 case VOGL_ENTRYPOINT_glGetVideoi64vNV:
9229 case VOGL_ENTRYPOINT_glGetVideoivNV:
9230 case VOGL_ENTRYPOINT_glGetVideoui64vNV:
9231 case VOGL_ENTRYPOINT_glGetVideouivNV:
9232 case VOGL_ENTRYPOINT_glGetnColorTableARB:
9233 case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
9234 case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
9235 case VOGL_ENTRYPOINT_glGetnHistogramARB:
9236 case VOGL_ENTRYPOINT_glGetnMapdvARB:
9237 case VOGL_ENTRYPOINT_glGetnMapfvARB:
9238 case VOGL_ENTRYPOINT_glGetnMapivARB:
9239 case VOGL_ENTRYPOINT_glGetnMinmaxARB:
9240 case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
9241 case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
9242 case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
9243 case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
9244 case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
9245 case VOGL_ENTRYPOINT_glGetnTexImageARB:
9246 case VOGL_ENTRYPOINT_glGetnUniformdvARB:
9247 case VOGL_ENTRYPOINT_glGetnUniformfvARB:
9248 case VOGL_ENTRYPOINT_glGetnUniformivARB:
9249 case VOGL_ENTRYPOINT_glGetnUniformuivARB:
9250 case VOGL_ENTRYPOINT_glIsBufferARB:
9251 case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
9252 case VOGL_ENTRYPOINT_glIsQueryARB:
9253 case VOGL_ENTRYPOINT_glIsSync:
9254 case VOGL_ENTRYPOINT_glPrioritizeTextures:
9255 case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
9257 if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
9259 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
9261 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
9267 if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
9268 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);
9270 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);
9271 return cStatusSoftFailure;
9275 m_last_processed_call_counter = trace_packet.get_call_counter();
9277 if (!m_pCur_context_state->m_inside_gl_begin)
9279 if (check_gl_error())
9280 return cStatusGLError;
9283 if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
9285 if ((status = post_draw_call()) != cStatusOK)
9292 //----------------------------------------------------------------------------------------------------------------------
9293 // vogl_gl_replayer::snapshot_backbuffer
9294 //----------------------------------------------------------------------------------------------------------------------
9295 void vogl_gl_replayer::snapshot_backbuffer()
9299 if (!m_pCur_context_state)
9301 vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
9305 uint recorded_width = m_pWindow->get_width();
9306 uint recorded_height = m_pWindow->get_height();
9308 uint width = 0, height = 0;
9309 m_pWindow->get_actual_dimensions(width, height);
9311 VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
9312 VOGL_NOTE_UNUSED(recorded_width);
9313 VOGL_NOTE_UNUSED(recorded_height);
9315 m_screenshot_buffer.resize(width * height * 3);
9317 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);
9320 process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
9323 if (m_flags & cGLReplayerDumpScreenshots)
9325 size_t png_size = 0;
9326 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
9328 dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
9329 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
9331 process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
9335 vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
9341 if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
9343 uint64_t backbuffer_crc64;
9345 if (m_flags & cGLReplayerSumHashing)
9347 backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9351 backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
9354 vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
9356 if (m_backbuffer_hash_filename.has_content())
9358 FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
9360 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
9363 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
9370 //----------------------------------------------------------------------------------------------------------------------
9371 // vogl_gl_replayer::is_valid_handle
9372 //----------------------------------------------------------------------------------------------------------------------
9373 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9380 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9382 switch (handle_namespace)
9384 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9386 VOGL_ASSERT(replay_handle32 == replay_handle);
9387 return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
9389 case VOGL_NAMESPACE_FRAMEBUFFERS:
9391 VOGL_ASSERT(replay_handle32 == replay_handle);
9392 return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
9394 case VOGL_NAMESPACE_TEXTURES:
9396 VOGL_ASSERT(replay_handle32 == replay_handle);
9397 return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
9399 case VOGL_NAMESPACE_RENDER_BUFFERS:
9401 VOGL_ASSERT(replay_handle32 == replay_handle);
9402 return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
9404 case VOGL_NAMESPACE_QUERIES:
9406 VOGL_ASSERT(replay_handle32 == replay_handle);
9407 return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
9409 case VOGL_NAMESPACE_SAMPLERS:
9411 VOGL_ASSERT(replay_handle32 == replay_handle);
9412 return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
9414 case VOGL_NAMESPACE_PROGRAMS:
9416 VOGL_ASSERT(replay_handle32 == replay_handle);
9417 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
9419 case VOGL_NAMESPACE_SHADERS:
9421 VOGL_ASSERT(replay_handle32 == replay_handle);
9422 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
9424 case VOGL_NAMESPACE_BUFFERS:
9426 VOGL_ASSERT(replay_handle32 == replay_handle);
9427 return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
9429 case VOGL_NAMESPACE_SYNCS:
9431 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9432 return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
9434 case VOGL_NAMESPACE_PROGRAM_ARB:
9436 VOGL_ASSERT(replay_handle32 == replay_handle);
9437 return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
9448 //----------------------------------------------------------------------------------------------------------------------
9449 // vogl_gl_replayer::remap_handle
9450 //----------------------------------------------------------------------------------------------------------------------
9451 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
9458 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
9460 switch (handle_namespace)
9462 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9464 VOGL_ASSERT(replay_handle32 == replay_handle);
9465 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
9466 return replay_handle32;
9469 case VOGL_NAMESPACE_FRAMEBUFFERS:
9471 VOGL_ASSERT(replay_handle32 == replay_handle);
9472 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
9473 return replay_handle32;
9476 case VOGL_NAMESPACE_TEXTURES:
9478 VOGL_ASSERT(replay_handle32 == replay_handle);
9480 uint32 trace_handle = replay_handle32;
9481 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
9482 return trace_handle;
9486 case VOGL_NAMESPACE_RENDER_BUFFERS:
9488 VOGL_ASSERT(replay_handle32 == replay_handle);
9489 GLuint trace_handle = replay_handle32;
9490 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
9491 return trace_handle;
9495 case VOGL_NAMESPACE_QUERIES:
9497 VOGL_ASSERT(replay_handle32 == replay_handle);
9498 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9499 return replay_handle32;
9502 case VOGL_NAMESPACE_SAMPLERS:
9504 VOGL_ASSERT(replay_handle32 == replay_handle);
9505 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9506 return replay_handle32;
9509 case VOGL_NAMESPACE_PROGRAMS:
9511 VOGL_ASSERT(replay_handle32 == replay_handle);
9512 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9513 GLuint trace_handle = replay_handle32;
9514 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9515 return trace_handle;
9518 case VOGL_NAMESPACE_SHADERS:
9520 VOGL_ASSERT(replay_handle32 == replay_handle);
9521 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9522 GLuint trace_handle = replay_handle32;
9523 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9524 return trace_handle;
9527 case VOGL_NAMESPACE_BUFFERS:
9529 VOGL_ASSERT(replay_handle32 == replay_handle);
9530 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9531 return replay_handle32;
9534 case VOGL_NAMESPACE_SYNCS:
9536 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9538 gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9539 if (it != m_replayer.get_shared_state()->m_syncs.end())
9541 VOGL_ASSERT(it->second == replay_sync);
9547 case VOGL_NAMESPACE_PROGRAM_ARB:
9549 VOGL_ASSERT(replay_handle32 == replay_handle);
9550 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9551 return replay_handle32;
9561 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));
9565 return replay_handle;
9568 //----------------------------------------------------------------------------------------------------------------------
9569 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9570 //----------------------------------------------------------------------------------------------------------------------
9571 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9575 if ((!replay_program) || (replay_location < 0))
9576 return replay_location;
9578 GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9580 glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9581 if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9583 const glsl_program_state &state = it->second;
9585 uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9586 if (loc_it != state.m_uniform_locations.end())
9587 return loc_it->first;
9590 vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9592 return replay_location;
9595 //----------------------------------------------------------------------------------------------------------------------
9596 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9597 //----------------------------------------------------------------------------------------------------------------------
9598 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9604 uint32 handle32 = static_cast<uint32>(replay_handle);
9606 switch (handle_namespace)
9608 case VOGL_NAMESPACE_TEXTURES:
9610 VOGL_ASSERT(handle32 == replay_handle);
9611 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9614 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9625 //----------------------------------------------------------------------------------------------------------------------
9626 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9627 //----------------------------------------------------------------------------------------------------------------------
9628 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9634 uint32 handle32 = static_cast<uint32>(trace_handle);
9636 switch (handle_namespace)
9638 case VOGL_NAMESPACE_TEXTURES:
9640 VOGL_ASSERT(handle32 == trace_handle);
9641 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9644 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9655 //----------------------------------------------------------------------------------------------------------------------
9656 // vogl_replayer::determine_used_program_handles
9657 //----------------------------------------------------------------------------------------------------------------------
9658 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9662 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9665 GLint cur_program_handle = 0;
9666 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9669 if (cur_program_handle)
9670 replay_program_handles.insert(cur_program_handle);
9673 // Scan for bound programs on all contexts in this sharegroup
9674 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9675 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9677 context_state *pContext = it->second;
9678 if (pContext->m_pShared_state == pContext_shareroot)
9680 if (pContext->m_cur_replay_program)
9681 replay_program_handles.insert(pContext->m_cur_replay_program);
9685 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9687 if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9690 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9692 // 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.
9693 if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9696 GLuint trace_handle = 0;
9697 bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9698 if (!refers_to_program)
9703 // 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
9704 // 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).
9705 if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9708 uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9712 VOGL_ASSERT(utils::is_32bit(replay_handle));
9714 replay_program_handles.insert(static_cast<uint32>(replay_handle));
9717 vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9722 //----------------------------------------------------------------------------------------------------------------------
9723 // vogl_replayer::fill_replay_handle_hash_set
9724 //----------------------------------------------------------------------------------------------------------------------
9725 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)
9729 replay_handle_hash.reset();
9730 replay_handle_hash.reserve(trace_to_replay_hash.size());
9731 for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9733 // Insert replay handles into destination hash table
9734 bool success = replay_handle_hash.insert(it->second).second;
9735 VOGL_ASSERT(success);
9736 VOGL_NOTE_UNUSED(success);
9740 //----------------------------------------------------------------------------------------------------------------------
9741 // vogl_replayer::snapshot_state
9742 //----------------------------------------------------------------------------------------------------------------------
9743 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9747 timed_scope ts(VOGL_METHOD_NAME);
9749 vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9751 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,
9752 m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9754 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))
9756 vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9758 vogl_delete(pSnapshot);
9764 vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9765 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9766 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()));
9768 vogl_client_side_array_desc_vec client_side_array_ptrs;
9769 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9770 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()));
9772 vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9773 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9774 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()));
9776 pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9778 vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9780 context_hash_map::iterator it;
9781 for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9783 context_state *pContext_state = it->second;
9785 if (pContext_state->m_deleted)
9787 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));
9791 vogl_capture_context_params temp_shadow_state;
9792 vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9794 if (pContext_state->m_has_been_made_current)
9796 status_t status = switch_contexts(it->first);
9797 if (status != cStatusOK)
9799 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9803 VOGL_ASSERT(m_pCur_context_state == pContext_state);
9805 if (m_pCur_context_state->m_inside_gl_begin)
9807 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));
9808 pSnapshot->set_is_restorable(false);
9812 // Init the shadow state needed by the snapshot code.
9813 if (!m_pCur_context_state->is_root_context())
9815 // Only fill in non-shared state.
9816 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9817 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9821 pShadow_state = &m_pCur_context_state->m_shadow_state;
9823 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9825 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9826 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9827 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9830 pShadow_state->m_buffer_targets.reset();
9831 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)
9833 GLuint trace_handle = buf_it->first;
9834 GLuint replay_handle = buf_it->second;
9836 gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9837 if (target_it == get_shared_state()->m_buffer_targets.end())
9839 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);
9842 GLenum target = target_it->second;
9844 pShadow_state->m_buffer_targets.insert(replay_handle, target);
9848 pShadow_state->m_syncs.reset();
9849 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9850 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)
9852 bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9853 VOGL_ASSERT(success);
9854 VOGL_NOTE_UNUSED(success);
9857 // Program handles filter
9858 pShadow_state->m_filter_program_handles = false;
9859 pShadow_state->m_program_handles_filter.reset();
9862 // 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).
9863 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9864 if ((pTrim_packets) && (optimize_snapshot))
9866 if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9868 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9869 pShadow_state->m_program_handles_filter.clear();
9873 pShadow_state->m_filter_program_handles = true;
9877 VOGL_NOTE_UNUSED(optimize_snapshot);
9878 VOGL_NOTE_UNUSED(pTrim_packets);
9881 // ARB program targets
9882 pShadow_state->m_arb_program_targets.reset();
9883 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)
9885 GLuint trace_handle = arb_prog_it->first;
9886 GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9887 if ((!trace_handle) || (!replay_handle))
9893 GLenum target = arb_prog_it->second;
9894 pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9897 // Deal with any currently mapped buffers.
9898 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9900 pShadow_state->m_mapped_buffers = mapped_bufs;
9902 if (mapped_bufs.size())
9904 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());
9906 for (uint i = 0; i < mapped_bufs.size(); i++)
9908 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9910 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9912 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9913 VOGL_CHECK_GL_ERROR;
9915 GL_ENTRYPOINT(glUnmapBuffer)(desc.m_target);
9916 VOGL_CHECK_GL_ERROR;
9920 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9921 VOGL_CHECK_GL_ERROR;
9925 } // if (!m_pCur_context_state->is_root_context())
9927 } // if (pContext_state->m_has_been_made_current)
9929 if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9931 vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9935 if ((pContext_state->m_has_been_made_current) && (m_pCur_context_state->is_root_context()))
9937 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
9939 // Now remap any mapped buffers
9940 for (uint i = 0; i < mapped_bufs.size(); i++)
9942 vogl_mapped_buffer_desc &desc = mapped_bufs[i];
9944 GLuint prev_handle = vogl_get_bound_gl_buffer(desc.m_target);
9946 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, desc.m_buffer);
9947 VOGL_CHECK_GL_ERROR;
9951 desc.m_pPtr = GL_ENTRYPOINT(glMapBufferRange)(desc.m_target, static_cast<GLintptr>(desc.m_offset), static_cast<GLsizeiptr>(desc.m_length), desc.m_access);
9952 VOGL_CHECK_GL_ERROR;
9956 desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(desc.m_target, desc.m_access);
9957 VOGL_CHECK_GL_ERROR;
9960 GL_ENTRYPOINT(glBindBuffer)(desc.m_target, prev_handle);
9961 VOGL_CHECK_GL_ERROR;
9967 if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9969 vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9973 vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9975 vogl_delete(pSnapshot);
9982 //----------------------------------------------------------------------------------------------------------------------
9983 // vogl_replayer::reset_state
9984 //----------------------------------------------------------------------------------------------------------------------
9985 void vogl_gl_replayer::reset_state()
9989 // Purposely does NOT destroy the cached snapshots
9991 destroy_pending_snapshot();
9994 m_pending_make_current_packet.clear();
9995 m_pending_window_resize_width = 0;
9996 m_pending_window_resize_height = 0;
9997 m_pending_window_resize_attempt_counter = 0;
10000 m_last_parsed_call_counter = -1;
10001 m_last_processed_call_counter = -1;
10002 m_at_frame_boundary = true;
10004 m_cur_trace_context = 0;
10005 m_cur_replay_context = 0;
10006 m_pCur_context_state = NULL;
10009 //if (m_pWindow->is_opened())
10010 // m_pWindow->clear_window();
10013 //----------------------------------------------------------------------------------------------------------------------
10014 // trace_to_replay_handle_remapper::is_valid_handle
10015 //----------------------------------------------------------------------------------------------------------------------
10016 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
10023 uint32 from_handle32 = static_cast<uint32>(from_handle);
10025 switch (handle_namespace)
10027 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10029 VOGL_ASSERT(from_handle32 == from_handle);
10030 return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
10032 case VOGL_NAMESPACE_TEXTURES:
10034 VOGL_ASSERT(from_handle32 == from_handle);
10035 return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
10037 case VOGL_NAMESPACE_SAMPLERS:
10039 VOGL_ASSERT(from_handle32 == from_handle);
10040 return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
10042 case VOGL_NAMESPACE_BUFFERS:
10044 VOGL_ASSERT(from_handle32 == from_handle);
10045 return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
10047 case VOGL_NAMESPACE_SHADERS:
10048 case VOGL_NAMESPACE_PROGRAMS:
10050 VOGL_ASSERT(from_handle32 == from_handle);
10051 return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
10053 case VOGL_NAMESPACE_FRAMEBUFFERS:
10055 VOGL_ASSERT(from_handle32 == from_handle);
10056 return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
10058 case VOGL_NAMESPACE_RENDER_BUFFERS:
10060 VOGL_ASSERT(from_handle32 == from_handle);
10061 return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
10063 case VOGL_NAMESPACE_QUERIES:
10065 VOGL_ASSERT(from_handle32 == from_handle);
10066 return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
10068 case VOGL_NAMESPACE_SYNCS:
10070 return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
10072 case VOGL_NAMESPACE_PROGRAM_ARB:
10074 return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
10085 //----------------------------------------------------------------------------------------------------------------------
10086 // trace_to_replay_handle_remapper::remap_handle
10087 //----------------------------------------------------------------------------------------------------------------------
10088 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
10093 return from_handle;
10095 uint32 from_handle32 = static_cast<uint32>(from_handle);
10097 switch (handle_namespace)
10099 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10101 VOGL_ASSERT(from_handle32 == from_handle);
10102 return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
10104 case VOGL_NAMESPACE_TEXTURES:
10106 VOGL_ASSERT(from_handle32 == from_handle);
10108 uint32 replay_handle = from_handle32;
10109 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
10110 return replay_handle;
10113 case VOGL_NAMESPACE_SAMPLERS:
10115 VOGL_ASSERT(from_handle32 == from_handle);
10116 return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
10118 case VOGL_NAMESPACE_BUFFERS:
10120 VOGL_ASSERT(from_handle32 == from_handle);
10121 return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
10123 case VOGL_NAMESPACE_SHADERS:
10124 case VOGL_NAMESPACE_PROGRAMS:
10126 VOGL_ASSERT(from_handle32 == from_handle);
10128 GLuint replay_handle = from_handle32;
10129 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
10130 return replay_handle;
10133 case VOGL_NAMESPACE_FRAMEBUFFERS:
10135 VOGL_ASSERT(from_handle32 == from_handle);
10136 return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
10138 case VOGL_NAMESPACE_RENDER_BUFFERS:
10140 VOGL_ASSERT(from_handle32 == from_handle);
10142 GLuint replay_handle = from_handle32;
10143 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
10144 return replay_handle;
10148 case VOGL_NAMESPACE_QUERIES:
10150 VOGL_ASSERT(from_handle32 == from_handle);
10151 return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
10153 case VOGL_NAMESPACE_SYNCS:
10155 return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
10157 case VOGL_NAMESPACE_PROGRAM_ARB:
10159 return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
10167 VOGL_ASSERT_ALWAYS;
10169 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
10171 return from_handle;
10174 //----------------------------------------------------------------------------------------------------------------------
10175 // trace_to_replay_handle_remapper::remap_location
10176 //----------------------------------------------------------------------------------------------------------------------
10177 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
10181 VOGL_NOTE_UNUSED(trace_program);
10183 // restoring declares, but doesn't need to remap
10184 VOGL_ASSERT_ALWAYS;
10186 return from_location;
10189 //----------------------------------------------------------------------------------------------------------------------
10190 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
10191 //----------------------------------------------------------------------------------------------------------------------
10192 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
10199 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
10200 if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
10202 m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10205 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
10208 //----------------------------------------------------------------------------------------------------------------------
10209 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
10210 //----------------------------------------------------------------------------------------------------------------------
10211 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)
10215 VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
10220 if (id == vogl_texcoord_pointer_array_id)
10222 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
10224 if (!m_replayer.m_client_side_texcoord_data[index].size())
10226 m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10229 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
10233 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
10235 if (!m_replayer.m_client_side_array_data[id].size())
10237 m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
10240 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
10244 //----------------------------------------------------------------------------------------------------------------------
10245 // trace_to_replay_handle_remapper::declare_handle
10246 //----------------------------------------------------------------------------------------------------------------------
10247 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)
10251 if ((!from_handle) || (!to_handle))
10253 VOGL_ASSERT_ALWAYS;
10257 uint32 from_handle32 = static_cast<uint32>(from_handle);
10258 uint32 to_handle32 = static_cast<uint32>(to_handle);
10260 switch (handle_namespace)
10262 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10264 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10265 m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
10268 case VOGL_NAMESPACE_TEXTURES:
10270 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10271 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
10272 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);
10275 case VOGL_NAMESPACE_SAMPLERS:
10277 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10278 m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
10281 case VOGL_NAMESPACE_BUFFERS:
10283 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10284 m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
10285 m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
10288 case VOGL_NAMESPACE_SHADERS:
10290 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10291 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
10292 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);
10295 case VOGL_NAMESPACE_PROGRAMS:
10297 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10298 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
10299 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);
10302 case VOGL_NAMESPACE_FRAMEBUFFERS:
10304 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10305 m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
10308 case VOGL_NAMESPACE_RENDER_BUFFERS:
10310 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10311 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
10312 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);
10315 case VOGL_NAMESPACE_QUERIES:
10317 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10318 m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
10319 m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
10322 case VOGL_NAMESPACE_SYNCS:
10324 m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
10327 case VOGL_NAMESPACE_PROGRAM_ARB:
10329 m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
10330 m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
10341 //----------------------------------------------------------------------------------------------------------------------
10342 // trace_to_replay_handle_remapper::delete_handle_and_object
10343 //----------------------------------------------------------------------------------------------------------------------
10344 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)
10348 if ((!from_handle) || (!to_handle))
10350 VOGL_ASSERT_ALWAYS;
10354 uint32 from_handle32 = static_cast<uint32>(from_handle);
10355 uint32 to_handle32 = static_cast<uint32>(to_handle);
10356 VOGL_NOTE_UNUSED(to_handle32);
10358 switch (handle_namespace)
10360 case VOGL_NAMESPACE_VERTEX_ARRAYS:
10362 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10363 m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
10364 vogl_destroy_gl_object(handle_namespace, to_handle);
10367 case VOGL_NAMESPACE_TEXTURES:
10369 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10370 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
10371 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);
10373 vogl_destroy_gl_object(handle_namespace, to_handle);
10376 case VOGL_NAMESPACE_SAMPLERS:
10378 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10379 m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
10380 vogl_destroy_gl_object(handle_namespace, to_handle);
10383 case VOGL_NAMESPACE_BUFFERS:
10385 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10386 m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
10387 m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
10388 vogl_destroy_gl_object(handle_namespace, to_handle);
10391 case VOGL_NAMESPACE_SHADERS:
10393 m_replayer.handle_delete_shader(from_handle32);
10396 case VOGL_NAMESPACE_PROGRAMS:
10398 m_replayer.handle_delete_program(from_handle32);
10401 case VOGL_NAMESPACE_FRAMEBUFFERS:
10403 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10404 m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
10405 vogl_destroy_gl_object(handle_namespace, to_handle);
10408 case VOGL_NAMESPACE_RENDER_BUFFERS:
10410 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10412 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
10413 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);
10415 vogl_destroy_gl_object(handle_namespace, to_handle);
10418 case VOGL_NAMESPACE_QUERIES:
10420 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10421 m_replayer.get_shared_state()->m_queries.erase(from_handle32);
10422 vogl_destroy_gl_object(handle_namespace, to_handle);
10425 case VOGL_NAMESPACE_SYNCS:
10427 m_replayer.get_shared_state()->m_syncs.erase(from_handle);
10428 vogl_destroy_gl_object(handle_namespace, to_handle);
10431 case VOGL_NAMESPACE_PROGRAM_ARB:
10433 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
10434 m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
10435 m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
10436 vogl_destroy_gl_object(handle_namespace, to_handle);
10447 //----------------------------------------------------------------------------------------------------------------------
10448 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
10449 //----------------------------------------------------------------------------------------------------------------------
10450 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)
10454 GLuint check_replay_handle = 0;
10455 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
10456 VOGL_ASSERT(check_replay_handle == to_program_handle);
10457 VOGL_NOTE_UNUSED(check_replay_handle);
10459 VOGL_NOTE_UNUSED(to_program_handle);
10461 glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
10463 glsl_program_state &prog_state = it->second;
10465 VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
10467 prog_state.m_uniform_locations.insert(from_location, to_location);
10470 //----------------------------------------------------------------------------------------------------------------------
10471 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
10472 //----------------------------------------------------------------------------------------------------------------------
10473 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
10479 uint32 handle32 = static_cast<uint32>(trace_handle);
10481 switch (handle_namespace)
10483 case VOGL_NAMESPACE_TEXTURES:
10485 VOGL_ASSERT(handle32 == trace_handle);
10486 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
10489 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
10500 //----------------------------------------------------------------------------------------------------------------------
10501 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
10502 //----------------------------------------------------------------------------------------------------------------------
10503 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
10509 uint32 handle32 = static_cast<uint32>(replay_handle);
10511 switch (handle_namespace)
10513 case VOGL_NAMESPACE_TEXTURES:
10515 VOGL_ASSERT(handle32 == replay_handle);
10516 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
10519 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
10530 //----------------------------------------------------------------------------------------------------------------------
10531 // vogl_replayer::restore_objects
10532 //----------------------------------------------------------------------------------------------------------------------
10533 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
10534 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,
10535 vogl_const_gl_object_state_ptr_vec &objects_to_delete)
10539 VOGL_NOTE_UNUSED(snapshot);
10541 if (m_flags & cGLReplayerVerboseMode)
10542 vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
10545 if (m_flags & cGLReplayerVerboseMode)
10548 const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10552 for (uint i = 0; i < object_ptrs.size(); i++)
10554 const vogl_gl_object_state *pState_obj = object_ptrs[i];
10556 if (pState_obj->get_type() != state_type)
10559 GLuint64 restore_handle = 0;
10560 if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10562 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);
10563 return cStatusHardFailure;
10567 if (pState_obj->get_marked_for_deletion())
10569 objects_to_delete.push_back(pState_obj);
10572 VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10574 switch (pState_obj->get_type())
10578 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10580 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10581 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10587 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10589 if (pProg->has_link_time_snapshot())
10591 vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10592 if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10594 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);
10598 get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10602 if (m_flags & cGLReplayerVerboseMode)
10604 if ((n & 255) == 255)
10605 vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10612 const vogl_buffer_state *pBuf = static_cast<const vogl_buffer_state *>(pState_obj);
10614 // Check if the buffer was mapped during the snapshot, if so remap it and record the ptr in the replayer's context shadow.
10615 if (pBuf->get_is_mapped())
10617 vogl_mapped_buffer_desc map_desc;
10618 map_desc.m_buffer = static_cast<GLuint>(restore_handle);
10619 map_desc.m_target = pBuf->get_target();
10620 map_desc.m_offset = pBuf->get_map_ofs();
10621 map_desc.m_length = pBuf->get_map_size();
10622 map_desc.m_access = pBuf->get_map_access();
10623 map_desc.m_range = pBuf->get_is_map_range();
10625 GLuint prev_handle = vogl_get_bound_gl_buffer(map_desc.m_target);
10627 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, map_desc.m_buffer);
10628 VOGL_CHECK_GL_ERROR;
10630 if (map_desc.m_range)
10632 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);
10633 VOGL_CHECK_GL_ERROR;
10637 map_desc.m_pPtr = GL_ENTRYPOINT(glMapBuffer)(map_desc.m_target, map_desc.m_access);
10638 VOGL_CHECK_GL_ERROR;
10641 GL_ENTRYPOINT(glBindBuffer)(map_desc.m_target, prev_handle);
10642 VOGL_CHECK_GL_ERROR;
10644 vogl_mapped_buffer_desc_vec &mapped_bufs = get_shared_state()->m_shadow_state.m_mapped_buffers;
10645 mapped_bufs.push_back(map_desc);
10655 if (m_flags & cGLReplayerVerboseMode)
10658 vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10660 vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10666 //----------------------------------------------------------------------------------------------------------------------
10667 // vogl_xfont_cache
10668 //----------------------------------------------------------------------------------------------------------------------
10669 class vogl_xfont_cache
10671 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10674 vogl_xfont_cache(Display *dpy)
10680 ~vogl_xfont_cache()
10691 for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10692 XFreeFont(m_dpy, it->second);
10696 XFontStruct *get_or_create(const char *pName)
10700 XFontStruct **ppXFont = m_xfonts.find_value(pName);
10704 XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10706 m_xfonts.insert(pName, pXFont);
10714 typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10715 xfont_map m_xfonts;
10718 //----------------------------------------------------------------------------------------------------------------------
10719 // vogl_replayer::restore_display_lists
10720 //----------------------------------------------------------------------------------------------------------------------
10721 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)
10725 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10726 VOGL_NOTE_UNUSED(snapshot);
10728 VOGL_ASSERT(m_cur_trace_context);
10732 const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10734 if (!disp_lists.size())
10737 vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10739 vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10741 const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10743 for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10745 GLuint trace_handle = it->first;
10746 const vogl_display_list &disp_list = it->second;
10750 VOGL_ASSERT_ALWAYS;
10754 GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10755 if (check_gl_error() || !replay_handle)
10756 goto handle_failure;
10758 if (disp_list.is_valid())
10760 if (disp_list.is_xfont())
10762 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10765 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);
10769 GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10774 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10776 if (check_gl_error() || !replay_handle)
10778 GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10781 goto handle_failure;
10784 const vogl_trace_packet_array &packets = disp_list.get_packets();
10786 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10788 if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10790 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);
10794 const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10796 if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10798 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);
10802 vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10804 gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10806 if (m_flags & cGLReplayerDebugMode)
10807 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10809 int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10810 int64_t prev_processed_call_counter = m_last_processed_call_counter;
10811 m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10812 m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10813 bool prev_at_frame_boundary = m_at_frame_boundary;
10815 const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10817 m_pCur_gl_packet = &m_temp2_gl_packet;
10819 vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10821 m_pCur_gl_packet = pPrev_gl_packet;
10823 m_last_parsed_call_counter = prev_parsed_call_counter;
10824 m_last_processed_call_counter = prev_processed_call_counter;
10825 m_at_frame_boundary = prev_at_frame_boundary;
10827 if (status != cStatusOK)
10829 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);
10834 // TODO: Set context state because we're currently generating a display list!
10835 if (disp_list.is_generating())
10837 VOGL_ASSERT_ALWAYS;
10840 GL_ENTRYPOINT(glEndList)();
10845 get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10847 if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10849 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);
10855 vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10860 return cStatusHardFailure;
10863 //----------------------------------------------------------------------------------------------------------------------
10864 // vogl_replayer::restore_general_state
10865 //----------------------------------------------------------------------------------------------------------------------
10866 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)
10870 VOGL_NOTE_UNUSED(snapshot);
10872 vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10873 persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10875 if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10876 return cStatusHardFailure;
10878 if (!m_pCur_context_state->m_context_info.is_core_profile())
10880 if (context_snapshot.get_texenv_state().is_valid())
10882 if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10883 return cStatusHardFailure;
10886 if (context_snapshot.get_material_state().is_valid())
10888 if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10889 return cStatusHardFailure;
10892 if (context_snapshot.get_light_state().is_valid())
10894 if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10895 return cStatusHardFailure;
10898 if (context_snapshot.get_matrix_state().is_valid())
10900 if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10901 return cStatusHardFailure;
10904 if (context_snapshot.get_polygon_stipple_state().is_valid())
10906 if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10907 return cStatusHardFailure;
10910 if (context_snapshot.get_arb_program_environment_state().is_valid())
10912 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10914 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10915 return cStatusHardFailure;
10919 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);
10924 if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10926 if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10927 return cStatusHardFailure;
10933 //----------------------------------------------------------------------------------------------------------------------
10934 // vogl_replayer::validate_program_and_shader_handle_tables
10935 //----------------------------------------------------------------------------------------------------------------------
10936 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10940 if (!m_pCur_context_state)
10943 if (!get_shared_state()->m_shadow_state.m_objs.check())
10944 vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10946 uint_vec replay_handles;
10947 get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10949 for (uint i = 0; i < replay_handles.size(); i++)
10951 GLuint replay_handle = replay_handles[i];
10952 GLuint trace_handle = replay_handle;
10953 bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10954 VOGL_ASSERT(map_succeeded);
10955 VOGL_NOTE_UNUSED(map_succeeded);
10957 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10958 VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10960 if (target == VOGL_PROGRAM_OBJECT)
10962 if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10964 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);
10967 if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10969 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);
10972 else if (target == VOGL_SHADER_OBJECT)
10974 if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10976 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);
10981 VOGL_ASSERT_ALWAYS;
10988 //----------------------------------------------------------------------------------------------------------------------
10989 // vogl_replayer::validate_textures
10990 //----------------------------------------------------------------------------------------------------------------------
10991 bool vogl_gl_replayer::validate_textures()
10995 if (!m_pCur_context_state)
10998 if (!get_shared_state()->m_shadow_state.m_textures.check())
10999 vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
11001 for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
11003 bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
11005 bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
11009 if (found_in_shadow)
11011 GLuint trace_handle = 0;
11012 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
11013 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);
11018 if (!found_in_shadow)
11020 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);
11028 //----------------------------------------------------------------------------------------------------------------------
11029 // vogl_replayer::update_context_shadows
11030 //----------------------------------------------------------------------------------------------------------------------
11031 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)
11035 VOGL_NOTE_UNUSED(snapshot);
11036 VOGL_NOTE_UNUSED(context_snapshot);
11037 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
11041 // Make sure shadow is good
11042 GLint actual_current_replay_program = 0;
11043 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
11046 m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
11047 if (!actual_current_replay_program)
11048 m_pCur_context_state->m_cur_trace_program = 0;
11051 GLuint trace_handle = actual_current_replay_program;
11052 if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
11054 process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
11056 m_pCur_context_state->m_cur_replay_program = 0;
11057 m_pCur_context_state->m_cur_trace_program = 0;
11061 m_pCur_context_state->m_cur_trace_program = trace_handle;
11065 check_program_binding_shadow();
11070 //----------------------------------------------------------------------------------------------------------------------
11071 // vogl_replayer::handle_marked_for_deleted_objects
11072 //----------------------------------------------------------------------------------------------------------------------
11073 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)
11077 if (m_flags & cGLReplayerVerboseMode)
11079 vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
11082 for (uint i = 0; i < objects_to_delete.size(); i++)
11084 const vogl_gl_object_state *pState_obj = objects_to_delete[i];
11086 GLuint64 trace_handle = pState_obj->get_snapshot_handle();
11087 GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
11089 if (m_flags & cGLReplayerVerboseMode)
11091 // This should be a rare/exception case so let's try to be a little paranoid.
11092 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,
11093 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
11096 GLboolean object_is_still_a_name = true;
11098 switch (pState_obj->get_type())
11102 handle_delete_program(static_cast<GLuint>(trace_handle));
11104 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
11110 handle_delete_shader(static_cast<GLuint>(trace_handle));
11112 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
11118 VOGL_ASSERT_ALWAYS;
11123 // "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."
11124 // Same for shaders.
11125 if (!object_is_still_a_name)
11127 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,
11128 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
11133 //----------------------------------------------------------------------------------------------------------------------
11134 // vogl_replayer::begin_applying_snapshot
11135 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
11136 //----------------------------------------------------------------------------------------------------------------------
11137 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
11141 if (!pSnapshot->is_valid())
11143 if (delete_snapshot_after_applying)
11144 vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
11146 return cStatusHardFailure;
11151 m_pPending_snapshot = pSnapshot;
11152 m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
11154 m_frame_index = pSnapshot->get_frame_index();
11155 m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
11156 m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
11157 m_at_frame_boundary = false;
11159 if (!(m_flags & cGLReplayerLockWindowDimensions))
11161 return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
11164 return process_applying_pending_snapshot();
11167 //----------------------------------------------------------------------------------------------------------------------
11168 // vogl_replayer::restore_context
11169 //----------------------------------------------------------------------------------------------------------------------
11170 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)
11174 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
11175 VOGL_NOTE_UNUSED(snapshot);
11177 // TODO: This always creates with attribs, also need to support plain glXCreateContext()
11179 Display *dpy = m_pWindow->get_display();
11180 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
11182 vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
11184 GLXContext replay_share_context = remap_context(trace_share_context);
11185 if ((trace_share_context) && (!replay_share_context))
11187 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));
11188 return cStatusHardFailure;
11191 GLboolean direct = context_snapshot.get_context_desc().get_direct();
11193 vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
11195 status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
11196 context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
11197 context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
11198 if (status != cStatusOK)
11200 vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
11204 // Has this context ever been made current?
11205 if (context_snapshot.get_context_info().is_valid())
11207 context_state *pContext_state = get_trace_context_state(trace_context);
11208 if (!pContext_state)
11210 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11211 return cStatusHardFailure;
11214 GLXContext replay_context = pContext_state->m_replay_context;
11215 if (!replay_context)
11217 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
11218 return cStatusHardFailure;
11221 GLXDrawable drawable = m_pWindow->get_xwindow();
11223 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
11226 vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
11227 return cStatusHardFailure;
11230 m_cur_trace_context = trace_context;
11231 m_cur_replay_context = replay_context;
11232 m_pCur_context_state = pContext_state;
11234 if (!handle_context_made_current())
11235 return cStatusHardFailure;
11241 //----------------------------------------------------------------------------------------------------------------------
11242 // vogl_replayer::process_applying_pending_snapshot
11243 //----------------------------------------------------------------------------------------------------------------------
11244 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
11248 if (!m_pPending_snapshot)
11251 timed_scope ts(VOGL_METHOD_NAME);
11253 const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
11255 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
11257 m_frame_index = snapshot.get_frame_index();
11258 m_last_parsed_call_counter = snapshot.get_gl_call_counter();
11259 m_last_processed_call_counter = snapshot.get_gl_call_counter();
11260 m_at_frame_boundary = snapshot.get_at_frame_boundary();
11262 // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
11263 for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
11264 m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
11266 for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
11267 m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
11269 for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
11270 m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
11272 const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
11274 vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
11275 vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
11277 status_t status = cStatusOK;
11278 uint total_contexts_restored = 0;
11279 bool restored_default_framebuffer = false;
11283 uint num_contexts_restored_in_this_pass = 0;
11285 for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
11287 if (!restore_context_ptrs[context_index])
11290 const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
11292 if (context_state.get_context_desc().get_trace_share_context())
11294 // Don't restore this context if its sharelist context hasn't been restored yet
11295 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
11299 status = restore_context(trace_to_replay_remapper, snapshot, context_state);
11300 if (status != cStatusOK)
11303 // Has this context ever been made current?
11304 if (context_state.get_context_info().is_valid())
11306 // 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!)
11307 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
11308 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
11310 if (m_flags & cGLReplayerLowLevelDebugMode)
11312 if (!validate_textures())
11313 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11316 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11318 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
11320 status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
11321 if (status != cStatusOK)
11324 if (m_flags & cGLReplayerLowLevelDebugMode)
11326 if (!validate_program_and_shader_handle_tables())
11327 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11329 if (!validate_textures())
11330 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11334 if (m_flags & cGLReplayerLowLevelDebugMode)
11336 if (!validate_textures())
11337 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11340 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
11341 if (status != cStatusOK)
11344 // Restore default framebuffer
11345 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
11347 restored_default_framebuffer = true;
11349 if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
11351 vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
11355 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
11356 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
11357 if (status != cStatusOK)
11360 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
11361 if (status != cStatusOK)
11364 if (m_flags & cGLReplayerLowLevelDebugMode)
11366 if (!validate_program_and_shader_handle_tables())
11367 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
11369 if (!validate_textures())
11370 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
11374 num_contexts_restored_in_this_pass++;
11376 total_contexts_restored++;
11378 restore_context_ptrs[context_index] = NULL;
11381 if (!num_contexts_restored_in_this_pass)
11385 if (total_contexts_restored != snapshot.get_contexts().size())
11387 vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
11391 for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
11393 const vogl_context_snapshot &context_state = *context_ptrs[context_index];
11395 if (!context_state.get_context_info().is_valid())
11398 status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
11399 if (status != cStatusOK)
11401 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()));
11405 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
11407 handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
11410 destroy_pending_snapshot();
11421 //----------------------------------------------------------------------------------------------------------------------
11422 // vogl_gl_replayer::write_trim_file_internal
11423 //----------------------------------------------------------------------------------------------------------------------
11424 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)
11426 // Open the output trace
11427 // 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.
11428 const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
11430 vogl_trace_packet trace_packet(&trace_gl_ctypes);
11432 // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
11433 bool found_state_snapshot = false;
11434 dynamic_string binary_snapshot_id, text_snapshot_id;
11436 bool is_at_start_of_trace = false;
11437 VOGL_NOTE_UNUSED(is_at_start_of_trace);
11439 int demarcation_packet_index = -1;
11440 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11442 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11443 if (packet_type != cTSPTGLEntrypoint)
11446 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11448 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11449 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11452 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11454 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11458 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11459 if (cmd == cITCRDemarcation)
11461 is_at_start_of_trace = true;
11462 demarcation_packet_index = packet_index;
11464 else if (cmd == cITCRKeyValueMap)
11466 key_value_map &kvm = trace_packet.get_key_value_map();
11468 dynamic_string cmd_type(kvm.get_string("command_type"));
11470 if (cmd_type == "state_snapshot")
11472 found_state_snapshot = true;
11474 text_snapshot_id = kvm.get_string("id");
11475 binary_snapshot_id = kvm.get_string("binary_id");
11480 vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
11481 if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
11483 console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11487 if (found_state_snapshot)
11489 // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
11490 if (trace_reader.get_archive_blob_manager().is_initialized())
11492 dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
11493 for (uint i = 0; i < blob_files.size(); i++)
11495 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
11498 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
11500 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
11502 vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
11510 // Copy over the source trace's backtrace map, machine info, etc. files.
11511 if (trace_reader.get_archive_blob_manager().is_initialized())
11513 // compiler_info.json
11514 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);
11515 // machine_info.json
11516 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);
11517 // backtrace_map_syms.json
11518 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);
11519 // backtrace_map_addrs.json
11520 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);
11523 vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
11525 if (!pTrim_snapshot.get())
11527 console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
11531 pTrim_snapshot->set_frame_index(0);
11534 if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
11536 console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
11537 trace_writer.close();
11538 file_utils::delete_file(trim_filename.get_ptr());
11542 vogl::vector<char> snapshot_data;
11543 doc.serialize(snapshot_data, true, 0, false);
11545 uint8_vec binary_snapshot_data;
11546 doc.binary_serialize(binary_snapshot_data);
11548 pTrim_snapshot.reset();
11550 // Write the state_snapshot file to the trace archive
11551 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));
11552 if (snapshot_id.is_empty())
11554 console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11555 trace_writer.close();
11556 file_utils::delete_file(trim_filename.get_ptr());
11561 *pSnapshot_id = snapshot_id;
11563 snapshot_data.clear();
11565 // Write the binary_state_snapshot file to the trace archive
11566 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));
11567 if (binary_snapshot_id.is_empty())
11569 console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
11570 trace_writer.close();
11571 file_utils::delete_file(trim_filename.get_ptr());
11575 binary_snapshot_data.clear();
11577 key_value_map snapshot_key_value_map;
11578 snapshot_key_value_map.insert("command_type", "state_snapshot");
11579 snapshot_key_value_map.insert("id", snapshot_id);
11580 snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
11582 dynamic_stream snapshot_stream(0);
11583 if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
11585 console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
11586 trace_writer.close();
11587 file_utils::delete_file(trim_filename.get_ptr());
11591 if (demarcation_packet_index >= 0)
11593 trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11594 demarcation_packet_index++;
11598 dynamic_stream demarcation_stream(0);
11599 vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11601 // Screw the ctypes packet, it's only used for debugging right now anyway.
11602 trim_packets.insert(0, snapshot_stream.get_buf());
11603 trim_packets.insert(1, demarcation_stream.get_buf());
11607 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11609 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11611 const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11613 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11614 if (packet_type == cTSPTEOF)
11616 else if (packet_type != cTSPTGLEntrypoint)
11618 VOGL_ASSERT_ALWAYS;
11621 if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11623 console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11624 trace_writer.close();
11625 file_utils::delete_file(trim_filename.get_ptr());
11630 bool success = trace_writer.close();
11632 console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11634 console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11639 //----------------------------------------------------------------------------------------------------------------------
11640 // vogl_gl_replayer::write_trim_file
11641 //----------------------------------------------------------------------------------------------------------------------
11642 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)
11648 console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11652 bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11654 if ((!from_start_of_frame) || (!trim_len))
11655 flags &= ~cWriteTrimFileOptimizeSnapshot;
11657 const uint trim_frame = static_cast<uint>(get_frame_index());
11658 const int64_t trim_call_counter = get_last_parsed_call_counter();
11660 // Read the desired packets from the source trace file
11661 vogl_trace_packet_array trim_packets;
11663 if ((trim_len) || (!trim_frame))
11665 console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11667 uint frames_to_read = trim_len;
11668 if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11669 frames_to_read = 1;
11671 uint actual_trim_len = 0;
11672 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);
11673 if (read_packets_status == vogl_trace_file_reader::cFailed)
11675 console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11679 if (actual_trim_len != frames_to_read)
11681 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);
11684 if (from_start_of_frame)
11686 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);
11688 if ((!trim_frame) && (!trim_len))
11690 // 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.
11691 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11693 vogl_trace_packet_array new_trim_packets;
11695 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11697 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11699 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11700 if (packet_type != cTSPTGLEntrypoint)
11703 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11705 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11706 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11709 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11711 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11715 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11717 new_trim_packets.push_back(packet_buf);
11719 if (cmd == cITCRDemarcation)
11723 trim_packets.swap(new_trim_packets);
11726 else if (trim_call_counter >= 0)
11728 uint orig_num_packets = trim_packets.size();
11729 uint total_erased_packets = 0;
11731 // Remove any calls before the current one.
11732 for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11734 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11737 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11739 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11741 trim_packets.erase(static_cast<uint>(packet_index));
11744 total_erased_packets++;
11748 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());
11752 if (!write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id))
11754 console::warning("%s: Trim file write failed, deleting invalid trim trace file %s\n", VOGL_METHOD_NAME, trim_filename.get_ptr());
11756 file_utils::delete_file(trim_filename.get_ptr());