1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_gl_replayer.cpp
27 #include "vogl_gl_replayer.h"
28 #include "vogl_general_context_state.h"
29 #include "vogl_sync_object.h"
30 #include "vogl_trace_file_writer.h"
31 #include "vogl_texture_format.h"
32 #include "gl_glx_replay_helper_macros.inc"
33 #include "vogl_backtrace.h"
35 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
36 #include "vogl_miniz.h"
38 #include "vogl_timer.h"
39 #include "vogl_file_utils.h"
41 #include "vogl_vector.h"
43 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC 129
44 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC 0x12345678
45 #define VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC -999999.0f
47 //----------------------------------------------------------------------------------------------------------------------
48 // glInterleavedArrays helper table
49 //----------------------------------------------------------------------------------------------------------------------
50 struct interleaved_array_desc_entry_t
66 #define _2f (sizeof(GLfloat) * 2)
67 #define _3f (sizeof(GLfloat) * 3)
68 #define _4f (sizeof(GLfloat) * 4)
69 #define _5f (sizeof(GLfloat) * 5)
70 #define _6f (sizeof(GLfloat) * 6)
71 #define _7f (sizeof(GLfloat) * 7)
72 #define _8f (sizeof(GLfloat) * 8)
73 #define _9f (sizeof(GLfloat) * 9)
74 #define _10f (sizeof(GLfloat) * 10)
75 #define _11f (sizeof(GLfloat) * 11)
76 #define _12f (sizeof(GLfloat) * 12)
77 #define _15f (sizeof(GLfloat) * 15)
78 #define _c (sizeof(GL_UNSIGNED_BYTE) * 4)
80 static const interleaved_array_desc_entry_t vogl_g_interleaved_array_descs[] =
82 // format et ec en st sc sv tc pc pn pv s
83 { GL_V2F, false, false, false, 0, 0, 2, 0, 0, 0, 0, _2f },
84 { GL_V3F, false, false, false, 0, 0, 3, 0, 0, 0, 0, _3f },
85 { GL_C4UB_V2F, false, true, false, 0, 4, 2, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _2f },
86 { GL_C4UB_V3F, false, true, false, 0, 4, 3, GL_UNSIGNED_BYTE, 0, 0, _c, _c + _3f },
87 { GL_C3F_V3F, false, true, false, 0, 3, 3, GL_FLOAT, 0, 0, _3f, _6f },
88 { GL_N3F_V3F, false, false, true, 0, 0, 3, 0, 0, 0, _3f, _6f },
89 { GL_C4F_N3F_V3F, false, true, true, 0, 4, 3, GL_FLOAT, 0, _4f, _7f, _10f },
90 { GL_T2F_V3F, true, false, false, 2, 0, 3, 0, 0, 0, _2f, _5f },
91 { GL_T4F_V4F, true, false, false, 4, 0, 4, 0, 0, 0, _4f, _8f },
92 { GL_T2F_C4UB_V3F, true, true, false, 2, 4, 3, GL_UNSIGNED_BYTE, _2f, 0, _c + _2f, _c + _5f },
93 { GL_T2F_C3F_V3F, true, true, false, 2, 3, 3, GL_FLOAT, 0, _2f, _5f, _8f },
94 { GL_T2F_N3F_V3F, true, false, true, 2, 0, 3, 0, 0, _2f, _5f, _8f },
95 { GL_T2F_C4F_N3F_V3F, true, true, true, 2, 4, 3, GL_FLOAT, _2f, _6f, _9f, _12f },
96 { GL_T4F_C4F_N3F_V4F, true, true, true, 4, 4, 4, GL_FLOAT, _4f, _8f, _11f, _15f }
113 #define VOGL_INTERLEAVED_ARRAY_SIZE (sizeof(vogl_g_interleaved_array_descs) / sizeof(vogl_g_interleaved_array_descs[0]))
115 //----------------------------------------------------------------------------------------------------------------------
116 // vogl_replayer::vogl_replayer
117 //----------------------------------------------------------------------------------------------------------------------
118 vogl_gl_replayer::vogl_gl_replayer()
120 m_swap_sleep_time(0),
121 m_dump_framebuffer_on_draw_prefix("screenshot"),
122 m_screenshot_prefix("screenshot"),
123 m_dump_framebuffer_on_draw_frame_index(-1),
124 m_dump_framebuffer_on_draw_first_gl_call_index(-1),
125 m_dump_framebuffer_on_draw_last_gl_call_index(-1),
126 m_ctypes_packet(&m_trace_gl_ctypes),
127 m_trace_pointer_size_in_bytes(0),
128 m_trace_pointer_size_in_uints(0),
129 m_temp_gl_packet(&m_trace_gl_ctypes),
130 m_temp2_gl_packet(&m_trace_gl_ctypes),
131 m_pCur_gl_packet(NULL),
133 m_pending_make_current_packet(&m_trace_gl_ctypes),
134 m_pending_window_resize_width(0),
135 m_pending_window_resize_height(0),
136 m_pending_window_resize_attempt_counter(false),
139 m_last_parsed_call_counter(-1),
140 m_last_processed_call_counter(-1),
141 m_cur_trace_context(0),
142 m_cur_replay_context(NULL),
143 m_pCur_context_state(NULL),
144 m_frame_draw_counter(0),
145 m_frame_draw_counter_kill_threshold(cUINT64_MAX),
147 m_pBlob_manager(NULL),
148 m_pPending_snapshot(NULL),
149 m_delete_pending_snapshot_after_applying(false),
150 m_replay_to_trace_remapper(*this)
154 m_trace_gl_ctypes.init();
157 //----------------------------------------------------------------------------------------------------------------------
158 // vogl_replayer::~vogl_replayer
159 //----------------------------------------------------------------------------------------------------------------------
160 vogl_gl_replayer::~vogl_gl_replayer()
167 //----------------------------------------------------------------------------------------------------------------------
168 // vogl_replayer::init
169 //----------------------------------------------------------------------------------------------------------------------
170 bool vogl_gl_replayer::init(uint flags, vogl_replay_window *pWindow, const vogl_trace_stream_start_of_file_packet &sof_packet, const vogl_blob_manager &blob_manager)
177 if ((!pWindow) || (!pWindow->is_opened()))
183 if ((sof_packet.m_pointer_sizes != sizeof(uint32)) && (sof_packet.m_pointer_sizes != sizeof(uint64_t)))
185 vogl_error_printf("%s: Invalid trace pointer size (%u)\n", VOGL_METHOD_NAME, m_sof_packet.m_pointer_sizes);
189 m_pBlob_manager = &blob_manager;
193 m_sof_packet = sof_packet;
194 m_trace_pointer_size_in_bytes = m_sof_packet.m_pointer_sizes;
195 m_trace_pointer_size_in_uints = m_sof_packet.m_pointer_sizes / sizeof(uint);
197 m_trace_gl_ctypes.init();
198 m_trace_gl_ctypes.change_pointer_sizes(m_trace_pointer_size_in_bytes);
200 if (!m_pWindow->is_opened())
202 const uint initial_window_width = 1024;
203 const uint initial_window_height = 768;
204 if (!m_pWindow->open(initial_window_width, initial_window_height))
206 vogl_error_printf("%s: Failed opening window!\n", VOGL_METHOD_NAME);
211 m_pCur_gl_packet = NULL;
215 m_last_parsed_call_counter = 0;
216 m_last_processed_call_counter = 0;
218 m_pending_make_current_packet.clear();
219 m_pending_window_resize_width = 0;
220 m_pending_window_resize_height = 0;
221 m_pending_window_resize_attempt_counter = 0;
223 m_at_frame_boundary = true;
225 m_cur_trace_context = 0;
226 m_cur_replay_context = 0;
227 m_pCur_context_state = NULL;
231 m_frame_draw_counter = 0;
232 m_frame_draw_counter_kill_threshold = cUINT64_MAX;
239 //----------------------------------------------------------------------------------------------------------------------
240 // vogl_replayer::deinit
241 //----------------------------------------------------------------------------------------------------------------------
242 void vogl_gl_replayer::deinit()
246 destroy_pending_snapshot();
249 // TODO: Make a 1st class snapshot cache class
250 for (uint i = 0; i < m_snapshots.size(); i++)
251 vogl_delete(m_snapshots[i].m_pSnapshot);
254 m_ctypes_packet.reset();
256 m_pCur_gl_packet = NULL;
260 m_last_parsed_call_counter = 0;
261 m_last_processed_call_counter = 0;
263 m_pending_make_current_packet.clear();
264 m_pending_window_resize_width = 0;
265 m_pending_window_resize_height = 0;
266 m_pending_window_resize_attempt_counter = 0;
268 m_at_frame_boundary = true;
270 m_cur_trace_context = 0;
271 m_cur_replay_context = 0;
272 m_pCur_context_state = NULL;
274 m_frame_draw_counter = 0;
275 m_frame_draw_counter_kill_threshold = cUINT32_MAX;
277 m_pBlob_manager = NULL;
280 m_swap_sleep_time = 0;
281 m_dump_framebuffer_on_draw_prefix = "screenshot";
282 m_screenshot_prefix = "screenshot";
283 m_backbuffer_hash_filename.clear();
284 m_dump_framebuffer_on_draw_frame_index = -1;
285 m_dump_framebuffer_on_draw_first_gl_call_index = -1;
286 m_dump_framebuffer_on_draw_last_gl_call_index = -1;
288 m_dump_frontbuffer_filename.clear();
293 //----------------------------------------------------------------------------------------------------------------------
294 // vogl_gl_replayer::dump_trace_gl_packet_debug_info
295 //----------------------------------------------------------------------------------------------------------------------
296 void vogl_gl_replayer::dump_trace_gl_packet_debug_info(const vogl_trace_gl_entrypoint_packet &gl_packet)
300 vogl_debug_printf("Trace packet: Total size %u, Param size: %u, Client mem size %u, Name value size %u, call %" PRIu64 ", ID: %s (%u), Thread ID: 0x%" PRIX64 ", Trace Context: 0x%" PRIX64 "\n",
302 gl_packet.m_param_size,
303 gl_packet.m_client_memory_size,
304 gl_packet.m_name_value_map_size,
305 gl_packet.m_call_counter,
306 g_vogl_entrypoint_descs[gl_packet.m_entrypoint_id].m_pName,
307 gl_packet.m_entrypoint_id,
308 gl_packet.m_thread_id,
309 gl_packet.m_context_handle);
312 //----------------------------------------------------------------------------------------------------------------------
313 // vogl_gl_replayer::dump_packet_as_func_call
314 //----------------------------------------------------------------------------------------------------------------------
315 void vogl_gl_replayer::dump_packet_as_func_call(const vogl_trace_packet& trace_packet)
321 if (!trace_packet.pretty_print(str, false))
322 vogl_error_printf("%s: packet pretty print failed!\n", VOGL_METHOD_NAME);
324 vogl_debug_printf("%s\n", str.get_ptr());
327 //----------------------------------------------------------------------------------------------------------------------
328 // vogl_replayer::process_next_packet
329 //----------------------------------------------------------------------------------------------------------------------
330 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(const vogl_trace_packet &gl_packet)
332 // TODO: Fix const correctness
333 return process_gl_entrypoint_packet((vogl_trace_packet &)gl_packet);
336 //----------------------------------------------------------------------------------------------------------------------
337 // vogl_replayer::process_next_packet
338 //----------------------------------------------------------------------------------------------------------------------
339 vogl_gl_replayer::status_t vogl_gl_replayer::process_next_packet(vogl_trace_file_reader &trace_reader)
343 vogl_trace_file_reader::trace_file_reader_status_t read_status = trace_reader.read_next_packet();
344 if (read_status == vogl_trace_file_reader::cEOF)
346 vogl_message_printf("At trace file EOF\n");
349 else if (read_status != vogl_trace_file_reader::cOK)
351 vogl_error_printf("Failed reading from trace file\n");
352 return cStatusHardFailure;
355 status_t status = cStatusOK;
357 switch (trace_reader.get_packet_type())
364 case cTSPTGLEntrypoint:
366 if (!m_temp_gl_packet.deserialize(trace_reader.get_packet_buf().get_ptr(), trace_reader.get_packet_buf().size(), false))
368 vogl_error_printf("Failed deserializing GL entrypoint packet\n");
369 status = cStatusHardFailure;
373 status = process_next_packet(m_temp_gl_packet);
379 vogl_message_printf("Encountered EOF packet in trace file\n");
380 status = cStatusAtEOF;
385 vogl_error_printf("Encountered unknown packet type in trace file\n");
386 status = cStatusSoftFailure;
393 vogl_error_printf("%s: %s failure processing GL entrypoint packet\n", VOGL_METHOD_NAME, (status == cStatusHardFailure) ? "Hard" : "Soft");
399 //----------------------------------------------------------------------------------------------------------------------
400 // vogl_replayer::process_pending_window_resize
401 //----------------------------------------------------------------------------------------------------------------------
402 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_window_resize(bool *pApplied_snapshot)
406 if (pApplied_snapshot)
407 *pApplied_snapshot = false;
409 status_t status = cStatusOK;
411 if (get_has_pending_window_resize())
413 status = process_frame_check_for_pending_window_resize();
414 if (status != cStatusOK)
418 if (m_pPending_snapshot)
420 if (pApplied_snapshot)
421 *pApplied_snapshot = true;
423 status_t status = process_applying_pending_snapshot();
424 if (status != cStatusOK)
431 //----------------------------------------------------------------------------------------------------------------------
432 // vogl_replayer::process_frame
433 //----------------------------------------------------------------------------------------------------------------------
434 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame(vogl_trace_file_reader &trace_reader)
438 status_t status = cStatusOK;
442 status = process_next_packet(trace_reader);
443 if ((status == cStatusNextFrame) || (status == cStatusResizeWindow) || (status == cStatusAtEOF) || (status == cStatusHardFailure))
450 //----------------------------------------------------------------------------------------------------------------------
451 // vogl_replayer::process_event
452 //----------------------------------------------------------------------------------------------------------------------
453 bool vogl_gl_replayer::update_window_dimensions()
457 m_pWindow->update_dimensions();
462 //----------------------------------------------------------------------------------------------------------------------
463 // vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap
464 //----------------------------------------------------------------------------------------------------------------------
465 bool vogl_gl_replayer::dump_frontbuffer_screenshot_before_next_swap(const dynamic_string &filename)
467 m_dump_frontbuffer_filename = filename;
472 //----------------------------------------------------------------------------------------------------------------------
473 // vogl_gl_replayer::dump_frontbuffer_to_file
474 //----------------------------------------------------------------------------------------------------------------------
475 bool vogl_gl_replayer::dump_frontbuffer_to_file(const dynamic_string &filename)
477 if ((!m_is_valid) || (!m_pWindow))
483 uint width = 0, height = 0;
484 m_pWindow->get_actual_dimensions(width, height);
486 m_screenshot_buffer.resize(width * height * 3);
488 bool success = vogl_copy_buffer_to_image(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size(), width, height, GL_RGB, GL_UNSIGNED_BYTE, false, 0, GL_FRONT);
491 vogl_error_printf("%s: Failed calling glReadPixels() to take frontbuffer screenshot!\n", VOGL_METHOD_NAME);
496 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
498 success = file_utils::write_buf_to_file(filename.get_ptr(), pPNG_data, png_size);
501 vogl_error_printf("%s: Failed writing PNG screenshot to file \"%s\"\n", filename.get_ptr(), VOGL_METHOD_NAME);
505 vogl_message_printf("Wrote PNG screenshot to file \"%s\"\n", filename.get_ptr());
513 //----------------------------------------------------------------------------------------------------------------------
514 // vogl_replayer::trigger_pending_window_resize
515 //----------------------------------------------------------------------------------------------------------------------
516 vogl_gl_replayer::status_t vogl_gl_replayer::trigger_pending_window_resize(uint win_width, uint win_height)
520 m_pending_window_resize_width = win_width;
521 m_pending_window_resize_height = win_height;
522 m_pending_window_resize_attempt_counter = 0;
523 m_time_since_pending_window_resize.start();
525 m_pWindow->resize(win_width, win_height);
527 if (m_flags & cGLReplayerVerboseMode)
528 vogl_debug_printf("%s: Waiting for window to resize to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
530 return cStatusResizeWindow;
533 //----------------------------------------------------------------------------------------------------------------------
534 // vogl_replayer::clear_pending_window_resize
535 //----------------------------------------------------------------------------------------------------------------------
536 void vogl_gl_replayer::clear_pending_window_resize()
540 m_pending_window_resize_width = 0;
541 m_pending_window_resize_height = 0;
542 m_pending_window_resize_attempt_counter = 0;
545 //----------------------------------------------------------------------------------------------------------------------
546 // vogl_replayer::process_frame_check_for_pending_window_resize
547 //----------------------------------------------------------------------------------------------------------------------
548 vogl_gl_replayer::status_t vogl_gl_replayer::process_frame_check_for_pending_window_resize()
552 const uint cMaxSecsToWait = 5;
554 if (!get_has_pending_window_resize())
557 if (m_pending_window_resize_attempt_counter >= cMaxSecsToWait)
559 vogl_warning_printf("Waited too long for window to resize to %ux%u, giving up and continuing replay\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
561 clear_pending_window_resize();
566 uint win_width = 0, win_height = 0;
567 m_pWindow->get_actual_dimensions(win_width, win_height);
569 if ((win_width != get_pending_window_resize_width()) ||
570 (win_height != get_pending_winow_resize_height()))
572 if (m_time_since_pending_window_resize.get_elapsed_secs() < 1.0f)
574 // sleep 1ms, then retry
576 return cStatusResizeWindow;
579 // What could possibly go wrong?
580 m_pending_window_resize_attempt_counter++;
581 if (m_pending_window_resize_attempt_counter < cMaxSecsToWait)
583 m_pWindow->resize(get_pending_window_resize_width(), get_pending_winow_resize_height());
585 m_time_since_pending_window_resize.start();
587 vogl_warning_printf("Waiting up to 5 secs for window to resize to %ux%u\n", get_pending_window_resize_width(), get_pending_winow_resize_height());
588 return cStatusResizeWindow;
592 clear_pending_window_resize();
593 m_pWindow->update_dimensions();
598 //----------------------------------------------------------------------------------------------------------------------
599 // vogl_replayer::destroy_pending_snapshot
600 //----------------------------------------------------------------------------------------------------------------------
601 void vogl_gl_replayer::destroy_pending_snapshot()
605 if (m_pPending_snapshot)
607 if (m_delete_pending_snapshot_after_applying)
609 // Ensure the snapshot cache can't be pointing to the snapshot, just to be safe.
610 // TODO: Make this a real class damn it.
611 for (uint i = 0; i < m_snapshots.size(); i++)
613 if (m_snapshots[i].m_pSnapshot == m_pPending_snapshot)
615 m_snapshots.erase(i);
620 vogl_delete(const_cast<vogl_gl_state_snapshot *>(m_pPending_snapshot));
623 m_pPending_snapshot = NULL;
626 m_delete_pending_snapshot_after_applying = false;
629 //----------------------------------------------------------------------------------------------------------------------
630 // vogl_replayer::check_gl_error
631 // Returns *true* on error, just like vogl_check_gl_error()
632 //----------------------------------------------------------------------------------------------------------------------
633 bool vogl_gl_replayer::check_gl_error_internal(bool quietly, const char *pFile, uint line, const char *pFunc)
640 // http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
641 // "Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
642 GLenum gl_err = GL_ENTRYPOINT(glGetError)();
643 if (gl_err == GL_NO_ERROR)
648 process_entrypoint_warning("%s: GL error: 0x%08X (%u): %s (Called from File: %s Line: %u Func: %s)\n", VOGL_METHOD_NAME, gl_err, gl_err, g_gl_enums.find_name("ErrorCode", gl_err), pFile ? pFile : "?", line, pFunc ? pFunc : "?");
657 //----------------------------------------------------------------------------------------------------------------------
658 // vogl_replayer::clear_contexts
659 //----------------------------------------------------------------------------------------------------------------------
660 void vogl_gl_replayer::clear_contexts()
664 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
666 context_state *pContext_state = it->second;
668 vogl_delete(pContext_state);
673 m_cur_trace_context = 0;
674 m_cur_replay_context = NULL;
675 m_pCur_context_state = NULL;
678 //----------------------------------------------------------------------------------------------------------------------
679 // vogl_replayer::destroy_contexts
680 //----------------------------------------------------------------------------------------------------------------------
681 void vogl_gl_replayer::destroy_contexts()
685 if ((m_contexts.size()) && (m_pWindow->get_display()) && (GL_ENTRYPOINT(glXMakeCurrent)) && (GL_ENTRYPOINT(glXDestroyContext)))
687 GL_ENTRYPOINT(glXMakeCurrent)(m_pWindow->get_display(), (GLXDrawable)NULL, NULL);
689 vogl::vector<context_state *> contexts_to_destroy;
690 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
691 contexts_to_destroy.push_back(it->second);
693 // Delete "tail" contexts (ones that are not referenced by any other context) in sharegroups first.
694 while (contexts_to_destroy.size())
696 for (int i = 0; i < static_cast<int>(contexts_to_destroy.size()); i++)
698 context_state *pContext_state = contexts_to_destroy[i];
700 vogl_trace_ptr_value trace_context = pContext_state->m_context_desc.get_trace_context();
702 bool skip_context = false;
703 for (int j = 0; j < static_cast<int>(contexts_to_destroy.size()); j++)
708 if (contexts_to_destroy[j]->m_context_desc.get_trace_share_context() == trace_context)
718 // This context may have been the sharegroup's root and could have been already deleted.
719 if (!pContext_state->m_deleted)
721 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), pContext_state->m_replay_context);
724 contexts_to_destroy.erase(i);
733 //----------------------------------------------------------------------------------------------------------------------
734 // vogl_replayer::define_new_context
735 //----------------------------------------------------------------------------------------------------------------------
736 vogl_gl_replayer::context_state *vogl_gl_replayer::define_new_context(
737 vogl_trace_context_ptr_value trace_context, GLXContext replay_context, vogl_trace_context_ptr_value trace_share_context, GLboolean direct, gl_entrypoint_id_t creation_func, const int *pAttrib_list, uint attrib_list_size)
741 if ((!trace_context) || (!replay_context))
747 context_state *pContext_state = vogl_new(context_state, *this);
749 pContext_state->m_trace_context = trace_context;
750 pContext_state->m_replay_context = replay_context;
752 pContext_state->m_context_desc.init(creation_func, direct, trace_context, trace_share_context, vogl_context_attribs(pAttrib_list, attrib_list_size));
754 if (trace_share_context)
756 for (context_hash_map::const_iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
758 if (trace_share_context == it->first)
760 context_state *pShare_context = it->second;
761 while (!pShare_context->is_root_context())
762 pShare_context = pShare_context->m_pShared_state;
764 pContext_state->m_pShared_state = pShare_context;
765 pContext_state->m_pShared_state->m_ref_count++;
771 if (!pContext_state->m_pShared_state)
773 process_entrypoint_error("%s: Unable to find trace share context handle 0x%" PRIX64 "!\n", VOGL_METHOD_NAME, trace_share_context);
777 m_contexts.insert(trace_context, pContext_state);
779 return pContext_state;
782 //----------------------------------------------------------------------------------------------------------------------
783 // vogl_replayer::remap_context
784 //----------------------------------------------------------------------------------------------------------------------
785 GLXContext vogl_gl_replayer::remap_context(vogl_trace_context_ptr_value trace_context)
792 context_hash_map::iterator it = m_contexts.find(trace_context);
793 return (it == m_contexts.end()) ? NULL : it->second->m_replay_context;
796 //----------------------------------------------------------------------------------------------------------------------
797 // vogl_replayer::destroy_context
798 //----------------------------------------------------------------------------------------------------------------------
799 bool vogl_gl_replayer::destroy_context(vogl_trace_context_ptr_value trace_context)
803 VOGL_ASSERT(trace_context);
805 context_hash_map::iterator it = m_contexts.find(trace_context);
806 if (it == m_contexts.end())
809 context_state *pContext_state = it->second;
810 VOGL_ASSERT(pContext_state->m_ref_count >= 1);
811 VOGL_ASSERT(!pContext_state->m_deleted);
813 if (pContext_state->is_share_context())
815 VOGL_ASSERT(pContext_state->m_ref_count == 1);
817 context_state *pShare_context = pContext_state->m_pShared_state;
818 VOGL_ASSERT(pShare_context->m_ref_count >= 1);
820 pShare_context->m_ref_count--;
821 if (!pShare_context->m_ref_count)
823 VOGL_ASSERT(pShare_context->m_deleted);
825 vogl_trace_context_ptr_value trace_share_context = pShare_context->m_context_desc.get_trace_context();
827 vogl_delete(pShare_context);
829 bool removed = m_contexts.erase(trace_share_context);
830 VOGL_NOTE_UNUSED(removed);
831 VOGL_ASSERT(removed);
834 vogl_delete(pContext_state);
836 bool removed = m_contexts.erase(trace_context);
837 VOGL_NOTE_UNUSED(removed);
838 VOGL_ASSERT(removed);
842 pContext_state->m_deleted = true;
843 pContext_state->m_ref_count--;
845 if (!pContext_state->m_ref_count)
849 vogl_delete(pContext_state);
851 bool removed = m_contexts.erase(trace_context);
852 VOGL_NOTE_UNUSED(removed);
853 VOGL_ASSERT(removed);
860 //----------------------------------------------------------------------------------------------------------------------
861 // vogl_replayer::set_client_side_array_data
862 // glVertexPointer, glNormalPointer, etc. client side data
863 //----------------------------------------------------------------------------------------------------------------------
864 bool vogl_gl_replayer::set_client_side_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
868 // TODO: Add early out
869 GLint prev_client_active_texture = 0;
870 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &prev_client_active_texture);
872 const uint tex_coords = math::minimum<uint>(m_pCur_context_state->m_context_info.is_core_profile() ? m_pCur_context_state->m_context_info.get_max_texture_units() : m_pCur_context_state->m_context_info.get_max_texture_coords(), VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS);
874 for (uint client_array_iter = 0; client_array_iter < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS; client_array_iter++)
876 const vogl_client_side_array_desc_t &desc = g_vogl_client_side_array_descs[client_array_iter];
878 const bool is_texcoord_array = (client_array_iter == vogl_texcoord_pointer_array_id);
881 uint base_key_index = 0x1000 + client_array_iter;
883 // Special case texcoord pointers, which are accessed via the client active texture.
884 if (is_texcoord_array)
887 base_key_index = 0x2000;
890 for (uint inner_iter = 0; inner_iter < n; inner_iter++)
892 uint key_index = base_key_index + inner_iter;
894 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(key_index));
895 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
899 if (is_texcoord_array)
901 GL_ENTRYPOINT(glClientActiveTexture)(GL_TEXTURE0 + inner_iter);
904 GLboolean is_enabled = GL_ENTRYPOINT(glIsEnabled)(desc.m_is_enabled);
909 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_binding, &binding);
914 GL_ENTRYPOINT(glGetPointerv)(desc.m_get_pointer, &ptr);
918 uint8_vec &array_data = is_texcoord_array ? m_client_side_texcoord_data[inner_iter] : m_client_side_array_data[client_array_iter];
919 if (ptr != array_data.get_ptr())
925 GLint type = GL_BOOL;
928 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_type, &type);
932 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_stride, &stride);
937 GL_ENTRYPOINT(glGetIntegerv)(desc.m_get_size, &size);
940 uint type_size = vogl_get_gl_type_size(type);
943 process_entrypoint_error("%s: Can't determine type size of enabled client side array set by func %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
947 if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glIndexPointerEXT) ||
948 (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glFogCoordPointerEXT) ||
949 (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glEdgeFlagPointerEXT))
953 else if ((desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointer) || (desc.m_entrypoint == VOGL_ENTRYPOINT_glNormalPointerEXT))
957 else if ((size < 1) && (size > 4))
959 process_entrypoint_error("%s: Size of client side array set by func %s must be between 1 and 4\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
964 stride = type_size * size;
966 uint first_vertex_ofs = (start + basevertex) * stride;
967 uint last_vertex_ofs = (end + basevertex) * stride;
968 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
969 uint total_data_size = last_vertex_ofs + stride;
974 process_entrypoint_error("%s: Failed finding client side vertex data blob set by func %s \n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName);
980 if (vertex_data_size != pVertex_blob->size())
982 process_entrypoint_error("%s: %s will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, vertex_data_size, pVertex_blob->size());
983 temp_blob = *pVertex_blob;
984 temp_blob.resize(vertex_data_size);
985 pVertex_blob = &temp_blob;
988 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
989 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
990 if (bytes_to_copy != pVertex_blob->size())
992 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
993 process_entrypoint_error("%s: %s accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[desc.m_entrypoint].m_pName, first_vertex_ofs + total_data_size);
996 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= array_data.size());
998 memcpy(array_data.get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1002 GL_ENTRYPOINT(glClientActiveTexture)(prev_client_active_texture);
1007 //----------------------------------------------------------------------------------------------------------------------
1008 // vogl_replayer::set_client_side_vertex_attrib_array_data
1009 // glVertexAttrib client side data
1010 //----------------------------------------------------------------------------------------------------------------------
1011 bool vogl_gl_replayer::set_client_side_vertex_attrib_array_data(const key_value_map &map, GLuint start, GLuint end, GLuint basevertex)
1015 // TODO: Add early out
1017 for (int vertex_attrib_index = 0; vertex_attrib_index < static_cast<int>(m_pCur_context_state->m_context_info.get_max_vertex_attribs()); vertex_attrib_index++)
1019 const uint8_vec *pVertex_blob = map.get_blob(static_cast<uint16>(vertex_attrib_index));
1021 // TODO: Check for case where blob (or map) is not present, but they still access client side data, this is a bad error
1026 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1031 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &cur_buf);
1035 GLvoid *attrib_ptr = NULL;
1036 GL_ENTRYPOINT(glGetVertexAttribPointerv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib_ptr);
1040 if (attrib_ptr != m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr())
1046 GLint attrib_size = 0;
1047 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib_size);
1049 GLint attrib_type = 0;
1050 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib_type);
1052 GLint attrib_stride = 0;
1053 GL_ENTRYPOINT(glGetVertexAttribiv)(vertex_attrib_index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib_stride);
1058 process_entrypoint_error("%s: Failed finding client side vertex data blob for generic vertex attrib %u\n", VOGL_METHOD_NAME, vertex_attrib_index);
1064 if ((attrib_size != GL_BGRA) && (attrib_size < 1) && (attrib_size > 4))
1066 process_entrypoint_error("%s: Enabled vertex attribute index %i has invalid size 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_size);
1069 if ((attrib_size >= 1) && (attrib_size <= 4))
1070 num_comps = attrib_size;
1072 uint type_size = vogl_get_gl_type_size(attrib_type);
1075 process_entrypoint_error("%s: Vertex attribute index %i has unsupported type 0x%0X\n", VOGL_METHOD_NAME, vertex_attrib_index, attrib_type);
1079 uint stride = attrib_stride ? attrib_stride : (type_size * num_comps);
1081 uint first_vertex_ofs = (start + basevertex) * stride;
1082 uint last_vertex_ofs = (end + basevertex) * stride;
1083 uint vertex_data_size = (last_vertex_ofs + stride) - first_vertex_ofs;
1084 uint total_data_size = last_vertex_ofs + stride;
1086 uint8_vec temp_blob;
1087 if (vertex_data_size != pVertex_blob->size())
1089 process_entrypoint_error("%s: Vertex attribute index %i will access more client side data (%u bytes) than stored in the trace (%u bytes), using what is in the trace and using zeros for the rest\n", VOGL_METHOD_NAME, vertex_attrib_index, vertex_data_size, pVertex_blob->size());
1090 temp_blob = *pVertex_blob;
1091 temp_blob.resize(vertex_data_size);
1092 pVertex_blob = &temp_blob;
1095 uint bytes_remaining_at_end = math::maximum<int>(0, (int)VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE - (int)first_vertex_ofs);
1096 uint bytes_to_copy = math::minimum<uint>(pVertex_blob->size(), bytes_remaining_at_end);
1097 if (bytes_to_copy != pVertex_blob->size())
1099 // Can't resize buffer, it could move and that would invalidate any VAO pointer bindings.
1100 process_entrypoint_error("%s: Vertex attribute index %i accesses too much client side data (%u bytes), increase VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE\n", VOGL_METHOD_NAME, vertex_attrib_index, first_vertex_ofs + total_data_size);
1103 VOGL_ASSERT((first_vertex_ofs + bytes_to_copy) <= m_client_side_vertex_attrib_data[vertex_attrib_index].size());
1105 memcpy(m_client_side_vertex_attrib_data[vertex_attrib_index].get_ptr() + first_vertex_ofs, pVertex_blob->get_ptr(), bytes_to_copy);
1111 //----------------------------------------------------------------------------------------------------------------------
1112 // vogl_replayer::draw_elements_client_side_array_setup
1113 //----------------------------------------------------------------------------------------------------------------------
1114 bool vogl_gl_replayer::draw_elements_client_side_array_setup(
1120 vogl_trace_ptr_value trace_indices_ptr_value, const GLvoid *&pIndices,
1122 bool has_valid_start_end,
1127 VOGL_NOTE_UNUSED(mode);
1131 GLuint element_array_buffer = 0;
1132 uint index_size = 0;
1135 index_size = vogl_get_gl_type_size(type);
1138 process_entrypoint_error("%s: Invalid type parameter 0x%08X\n", VOGL_METHOD_NAME, type);
1142 element_array_buffer = vogl_get_bound_gl_buffer(GL_ELEMENT_ARRAY_BUFFER);
1143 if (element_array_buffer)
1145 // trace_indices_ptr_value is actually an offset into the buffer, not a real trace ptr
1146 pIndices = reinterpret_cast<GLvoid *>(trace_indices_ptr_value);
1152 process_entrypoint_warning("%s: count parameter is <= 0 (%i)\n", VOGL_METHOD_NAME, count);
1156 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
1159 if ((indexed) && (!element_array_buffer) && (trace_indices_ptr_value))
1161 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob. Can't remap indices pointer!\n", VOGL_METHOD_NAME);
1162 if (trace_indices_ptr_value)
1164 // We can't remap the pointer to valid memory, so give up.
1169 // TODO: Check for client side array usage but no data in blob (which would be a desync or error)
1173 // TODO: If a VAO is bound, client side data isn't supported according to this:
1174 // http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
1176 //GLint current_vertex_array_binding = 0;
1177 //ACTUAL_GL_ENTRYPOINT(glGetIntegerv)(GL_VERTEX_ARRAY_BINDING, ¤t_vertex_array_binding);
1179 if ((indexed) && (!element_array_buffer))
1181 const uint8_vec *pIndices_vec = map.get_blob(string_hash("indices"));
1184 process_entrypoint_error("%s: No element array buffer is bound, but key value map doesn't have an indices blob\n", VOGL_METHOD_NAME);
1188 pIndices = pIndices_vec->get_ptr();
1191 process_entrypoint_error("%s: No element array buffer is bound, but key value map has an empty indices blob\n", VOGL_METHOD_NAME);
1195 if ((pIndices_vec->size() / index_size) != static_cast<uint>(count))
1197 process_entrypoint_error("%s: Client side index data blob stored in packet is too small (wanted %u indices, got %u indices)\n", VOGL_METHOD_NAME, count, pIndices_vec->size() / index_size);
1202 if ((indexed) && (!has_valid_start_end))
1204 uint total_index_data_size = count * index_size;
1206 const uint8 *pIndices_to_scan = static_cast<const uint8 *>(pIndices);
1208 if (element_array_buffer)
1210 if (m_index_data.size() < total_index_data_size)
1211 m_index_data.resize(total_index_data_size);
1213 pIndices_to_scan = m_index_data.get_ptr();
1217 GL_ENTRYPOINT(glGetBufferSubData)(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)pIndices, total_index_data_size, m_index_data.get_ptr());
1219 if (check_gl_error())
1221 process_entrypoint_warning("%s: GL error while trying to retrieve index buffer data\n", VOGL_METHOD_NAME);
1223 memset(m_index_data.get_ptr(), 0, total_index_data_size);
1227 start = cUINT32_MAX;
1230 for (int i = 0; i < count; i++)
1234 if (type == GL_UNSIGNED_BYTE)
1235 v = pIndices_to_scan[i];
1236 else if (type == GL_UNSIGNED_SHORT)
1237 v = reinterpret_cast<const uint16 *>(pIndices_to_scan)[i];
1238 else if (type == GL_UNSIGNED_INT)
1239 v = reinterpret_cast<const uint32 *>(pIndices_to_scan)[i];
1242 process_entrypoint_error("%s: Invalid index type\n", VOGL_METHOD_NAME);
1246 start = math::minimum(start, v);
1247 end = math::maximum(end, v);
1250 has_valid_start_end = true;
1253 if (!set_client_side_array_data(map, start, end, basevertex))
1256 if (!set_client_side_vertex_attrib_array_data(map, start, end, basevertex))
1262 //----------------------------------------------------------------------------------------------------------------------
1263 // vogl_replayer::determine_uniform_replay_location
1264 //----------------------------------------------------------------------------------------------------------------------
1265 GLint vogl_gl_replayer::determine_uniform_replay_location(GLuint trace_program, GLint trace_location)
1269 GLint replay_location = trace_location;
1271 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
1272 if (it == get_shared_state()->m_glsl_program_hash_map.end())
1274 process_entrypoint_warning("%s: Failed looking up current trace program in GLSL program hash map\n", VOGL_METHOD_NAME);
1278 glsl_program_state &state = it->second;
1280 uniform_location_hash_map::const_iterator loc_it = state.m_uniform_locations.find(trace_location);
1281 if (loc_it == state.m_uniform_locations.end())
1283 process_entrypoint_warning("%s: Failed looking up uniform location index\n", VOGL_METHOD_NAME);
1287 replay_location = loc_it->second;
1290 return replay_location;
1293 //----------------------------------------------------------------------------------------------------------------------
1294 // vogl_replayer::process_entrypoint_print_summary_context
1295 //----------------------------------------------------------------------------------------------------------------------
1296 void vogl_gl_replayer::process_entrypoint_print_summary_context(eConsoleMessageType msg_type)
1300 if (!m_pCur_gl_packet)
1303 console::printf(msg_type, "While processing GL entrypoint packet func %s, frame %u, swaps %u, GL call counter %" PRIu64 ", packet start trace context 0x%" PRIX64 ", cur trace context 0x%" PRIX64 ", trace thread 0x%" PRIX64 ":\n",
1304 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
1305 m_frame_index, m_total_swaps,
1306 m_pCur_gl_packet->get_entrypoint_packet().m_call_counter,
1307 m_pCur_gl_packet->get_entrypoint_packet().m_context_handle,
1308 m_cur_trace_context,
1309 m_pCur_gl_packet->get_entrypoint_packet().m_thread_id);
1312 dynamic_string_array backtrace;
1313 if (get_printable_backtrace(backtrace))
1315 console::printf("Backtrace:\n");
1316 for (uint i = 0; i < backtrace.size(); i++)
1317 console::printf("%s\n", backtrace[i].get_ptr());
1322 //----------------------------------------------------------------------------------------------------------------------
1323 // vogl_replayer::print_detailed_context
1324 //----------------------------------------------------------------------------------------------------------------------
1325 void vogl_gl_replayer::print_detailed_context(eConsoleMessageType msg_type)
1331 vogl_loose_file_blob_manager blob_file_manager;
1332 blob_file_manager.init(cBMFWritable);
1334 vogl_trace_packet::json_serialize_params serialize_params;
1335 serialize_params.m_output_basename = "replay_error";
1336 serialize_params.m_cur_frame = m_frame_index;
1337 serialize_params.m_blob_file_size_threshold = 1024;
1338 serialize_params.m_pBlob_manager = (m_flags & cGLReplayerDumpPacketBlobFilesOnError) ? &blob_file_manager : NULL;
1339 m_pCur_gl_packet->json_serialize(node, serialize_params);
1341 dynamic_string node_str;
1342 node.serialize(node_str, true, 0);
1343 console::printf(msg_type, "Packet at call counter %" PRIu64 " as JSON:\n%s\n", m_pCur_gl_packet->get_entrypoint_packet().m_call_counter, node_str.get_ptr());
1346 //----------------------------------------------------------------------------------------------------------------------
1347 // vogl_replayer::process_entrypoint_msg_print_detailed_context
1348 //----------------------------------------------------------------------------------------------------------------------
1349 void vogl_gl_replayer::process_entrypoint_msg_print_detailed_context(eConsoleMessageType msg_type)
1353 dump_packet_as_func_call(*m_pCur_gl_packet);
1355 if (!(m_flags & cGLReplayerDumpPacketsOnError))
1358 print_detailed_context(msg_type);
1361 //----------------------------------------------------------------------------------------------------------------------
1362 // vogl_replayer::process_entrypoint_info
1363 //----------------------------------------------------------------------------------------------------------------------
1364 void vogl_gl_replayer::process_entrypoint_info(const char *pFmt, ...)
1368 process_entrypoint_print_summary_context(cInfoConsoleMessage);
1371 va_start(args, pFmt);
1372 console::vprintf(cInfoConsoleMessage, pFmt, args);
1375 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1378 //----------------------------------------------------------------------------------------------------------------------
1379 // vogl_replayer::process_entrypoint_message
1380 //----------------------------------------------------------------------------------------------------------------------
1381 void vogl_gl_replayer::process_entrypoint_message(const char *pFmt, ...)
1385 process_entrypoint_print_summary_context(cMessageConsoleMessage);
1388 va_start(args, pFmt);
1389 console::vprintf(cMessageConsoleMessage, pFmt, args);
1392 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1395 //----------------------------------------------------------------------------------------------------------------------
1396 // vogl_replayer::process_entrypoint_warning
1397 //----------------------------------------------------------------------------------------------------------------------
1398 void vogl_gl_replayer::process_entrypoint_warning(const char *pFmt, ...)
1402 process_entrypoint_print_summary_context(cWarningConsoleMessage);
1405 va_start(args, pFmt);
1406 console::vprintf(cWarningConsoleMessage, pFmt, args);
1409 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1412 //----------------------------------------------------------------------------------------------------------------------
1413 // vogl_replayer::process_entrypoint_error
1414 //----------------------------------------------------------------------------------------------------------------------
1415 void vogl_gl_replayer::process_entrypoint_error(const char *pFmt, ...)
1419 process_entrypoint_print_summary_context(cErrorConsoleMessage);
1422 va_start(args, pFmt);
1423 console::vprintf(cErrorConsoleMessage, pFmt, args);
1426 process_entrypoint_msg_print_detailed_context(cInfoConsoleMessage);
1429 //----------------------------------------------------------------------------------------------------------------------
1430 // vogl_replayer::switch_contexts
1431 //----------------------------------------------------------------------------------------------------------------------
1432 vogl_gl_replayer::status_t vogl_gl_replayer::switch_contexts(vogl_trace_context_ptr_value trace_context)
1436 //vogl_trace_context_ptr_value trace_context = gl_packet.m_context_handle;
1437 if (trace_context == m_cur_trace_context)
1440 if (m_flags & cGLReplayerDebugMode)
1442 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));
1445 // pContext_state will be NULL if they are unmapping!
1446 context_state *pContext_state = get_trace_context_state(trace_context);
1447 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1449 const Display *dpy = m_pWindow->get_display();
1450 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1452 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1455 process_entrypoint_error("%s: Failed switching current trace context to 0x%" PRIX64 "\n", VOGL_METHOD_NAME, trace_context);
1456 return cStatusHardFailure;
1459 m_cur_trace_context = trace_context;
1460 m_cur_replay_context = replay_context;
1461 m_pCur_context_state = pContext_state;
1466 //----------------------------------------------------------------------------------------------------------------------
1467 // vogl_replayer::debug_callback_arb
1468 //----------------------------------------------------------------------------------------------------------------------
1469 void vogl_gl_replayer::debug_callback_arb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *pUser_param)
1473 VOGL_NOTE_UNUSED(length);
1475 char final_message[4096];
1477 context_state *pContext_state = (context_state *)(pUser_param);
1479 vogl_format_debug_output_arb(final_message, sizeof(final_message), source, type, id, severity, reinterpret_cast<const char *>(message));
1483 vogl_warning_printf("%s: Trace context: 0x%" PRIX64 ", Replay context 0x%" PRIX64 ", Last trace call counter: %" PRIu64 "\n%s\n", VOGL_FUNCTION_NAME,
1484 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);
1488 vogl_warning_printf("%s: %s\n", VOGL_FUNCTION_NAME, final_message);
1492 //----------------------------------------------------------------------------------------------------------------------
1493 // vogl_replayer::is_extension_supported
1494 //----------------------------------------------------------------------------------------------------------------------
1495 bool vogl_gl_replayer::is_extension_supported(const char *pExt)
1499 if ((m_pCur_context_state) && (m_pCur_context_state->m_context_info.is_valid()))
1501 return m_pCur_context_state->m_context_info.supports_extension(pExt);
1509 //----------------------------------------------------------------------------------------------------------------------
1510 // vogl_replayer::context_state::handle_context_made_current
1511 //----------------------------------------------------------------------------------------------------------------------
1512 bool vogl_gl_replayer::context_state::handle_context_made_current()
1516 if (m_has_been_made_current)
1519 VOGL_CHECK_GL_ERROR;
1521 m_has_been_made_current = true;
1523 if (!m_context_info.init(m_context_desc))
1525 vogl_error_printf("%s: vogl_context_info::init() failed!\n", VOGL_METHOD_NAME);
1529 if (!m_context_info.get_max_vertex_attribs())
1531 vogl_warning_printf("%s: GL_MAX_VERTEX_ATTRIBS is 0\n", VOGL_METHOD_NAME);
1533 else if (m_context_info.get_max_vertex_attribs() >= VOGL_MAX_SUPPORTED_GL_VERTEX_ATTRIBUTES)
1535 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);
1539 if (m_replayer.m_flags & cGLReplayerLowLevelDebugMode)
1541 vogl_debug_printf("%s: Creating dummy handles\n", VOGL_METHOD_NAME);
1544 // Generate a bunch of replay handles, so the trace and replay namespaces are totally different to shake out handle or target remapping bugs
1545 // TODO: All more object types
1546 vogl::vector<GLuint> dummy_handles(65536);
1548 GL_ENTRYPOINT(glGenTextures)(4000, dummy_handles.get_ptr());
1549 GL_ENTRYPOINT(glGenBuffers)(6000, dummy_handles.get_ptr());
1550 GL_ENTRYPOINT(glGenLists)(8000);
1551 GL_ENTRYPOINT(glGenQueries)(10000, dummy_handles.get_ptr());
1553 GL_ENTRYPOINT(glGenVertexArrays)(12000, dummy_handles.get_ptr());
1554 GL_ENTRYPOINT(glGenProgramsARB)(14000, dummy_handles.get_ptr());
1555 GL_ENTRYPOINT(glGenFramebuffers)(16000, dummy_handles.get_ptr());
1556 GL_ENTRYPOINT(glGenSamplers)(18000, dummy_handles.get_ptr());
1557 GL_ENTRYPOINT(glGenRenderbuffers)(20000, dummy_handles.get_ptr());
1559 for (uint i = 0; i < 22000; i++)
1560 GL_ENTRYPOINT(glCreateProgram)();
1562 vogl_debug_printf("%s: Finished creating dummy handles\n", VOGL_METHOD_NAME);
1565 VOGL_CHECK_GL_ERROR;
1570 //----------------------------------------------------------------------------------------------------------------------
1571 // vogl_replayer::handle_context_made_current
1572 //----------------------------------------------------------------------------------------------------------------------
1573 bool vogl_gl_replayer::handle_context_made_current()
1577 if (!m_pCur_context_state->handle_context_made_current())
1580 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")))
1582 GL_ENTRYPOINT(glDebugMessageCallbackARB)(debug_callback_arb, (GLvoid *)m_pCur_context_state);
1583 GL_ENTRYPOINT(glEnable)(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1587 if (m_flags & cGLReplayerVerboseMode)
1589 vogl_debug_printf("%s: Trace context: 0x%" PRIX64 ", replay context 0x%" PRIX64 ", GL_VERSION: %s\n",
1591 (uint64_t)m_cur_trace_context,
1592 (uint64_t)m_cur_replay_context,
1593 m_pCur_context_state->m_context_info.get_version_str().get_ptr());
1599 //----------------------------------------------------------------------------------------------------------------------
1600 // vogl_replayer::dump_context_attrib_list
1601 //----------------------------------------------------------------------------------------------------------------------
1602 void vogl_gl_replayer::dump_context_attrib_list(const int *pAttrib_list, uint size)
1608 vogl_debug_printf("Attrib list is NULL\n");
1611 vogl_debug_printf("Context attribs:\n");
1618 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1622 uint key = pAttrib_list[ofs];
1629 vogl_error_printf("%s: Attrib list ended prematurely (must end in a 0 key)\n", VOGL_METHOD_NAME);
1633 uint value = pAttrib_list[ofs];
1636 vogl_debug_printf("Key: %s (0x%08X), Value: 0x%08X\n", g_gl_enums.find_name(key, "GLX"), key, value);
1638 vogl_debug_printf("End of context attribs\n");
1641 //----------------------------------------------------------------------------------------------------------------------
1642 // vogl_replayer::find_attrib_key
1643 //----------------------------------------------------------------------------------------------------------------------
1644 int vogl_gl_replayer::find_attrib_key(const vogl::vector<int> &attrib_list, int key_to_find)
1649 while (ofs < attrib_list.size())
1651 int key = attrib_list[ofs];
1655 if (++ofs >= attrib_list.size())
1657 process_entrypoint_warning("%s: Failed parsing attrib list, this call is probably going to fail\n", VOGL_METHOD_NAME);
1661 if (key == key_to_find)
1669 //----------------------------------------------------------------------------------------------------------------------
1670 // vogl_replayer::create_context_attribs
1671 //----------------------------------------------------------------------------------------------------------------------
1672 vogl_gl_replayer::status_t vogl_gl_replayer::create_context_attribs(
1673 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,
1674 const int *pTrace_attrib_list, int trace_attrib_list_size, bool expecting_attribs)
1678 vogl::vector<int> temp_attrib_list;
1680 if ((pTrace_attrib_list) && (trace_attrib_list_size))
1682 temp_attrib_list.append(pTrace_attrib_list, trace_attrib_list_size);
1683 if (temp_attrib_list.back() != 0)
1685 process_entrypoint_warning("%s: attrib list does not end with 0\n", VOGL_METHOD_NAME);
1690 if (expecting_attribs)
1692 if (m_flags & cGLReplayerVerboseMode)
1693 process_entrypoint_message("%s: No attrib list found in trace, assuming an attrib list ending with 0\n", VOGL_METHOD_NAME);
1696 temp_attrib_list.push_back(0);
1699 if (m_flags & cGLReplayerForceDebugContexts)
1701 // See http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
1702 int context_flags_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_FLAGS_ARB);
1703 if (context_flags_ofs < 0)
1705 temp_attrib_list.back() = GLX_CONTEXT_FLAGS_ARB;
1706 temp_attrib_list.push_back(GLX_CONTEXT_DEBUG_BIT_ARB);
1707 temp_attrib_list.push_back(0);
1709 if (m_flags & cGLReplayerVerboseMode)
1710 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);
1714 temp_attrib_list[context_flags_ofs] |= GLX_CONTEXT_DEBUG_BIT_ARB;
1716 if (m_flags & cGLReplayerVerboseMode)
1717 process_entrypoint_warning("%s: Slamming on GLX_CONTEXT_DEBUG_BIT_ARB bit to enable debug context\n", VOGL_METHOD_NAME);
1720 int context_major_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MAJOR_VERSION_ARB);
1721 int context_minor_version_ofs = find_attrib_key(temp_attrib_list, GLX_CONTEXT_MINOR_VERSION_ARB);
1723 bool slammed_up_to_3_0 = false;
1724 if (context_major_version_ofs < 0)
1726 // 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).
1728 temp_attrib_list.back() = GLX_CONTEXT_MAJOR_VERSION_ARB;
1729 temp_attrib_list.push_back(3);
1730 temp_attrib_list.push_back(0);
1732 slammed_up_to_3_0 = true;
1735 else if (temp_attrib_list[context_major_version_ofs] < 3)
1737 temp_attrib_list[context_major_version_ofs] = 3;
1739 slammed_up_to_3_0 = true;
1742 if (slammed_up_to_3_0)
1744 if (context_minor_version_ofs < 0)
1746 temp_attrib_list.back() = GLX_CONTEXT_MINOR_VERSION_ARB;
1747 temp_attrib_list.push_back(0);
1748 temp_attrib_list.push_back(0);
1752 temp_attrib_list[context_minor_version_ofs] = 0;
1755 process_entrypoint_warning("%s: Forcing GL context version up to 3.0 due to debug context usage\n", VOGL_METHOD_NAME);
1759 const int *pAttrib_list = temp_attrib_list.get_ptr();
1760 const uint attrib_list_size = temp_attrib_list.size();
1762 if (m_flags & cGLReplayerVerboseMode)
1763 dump_context_attrib_list(pAttrib_list, attrib_list_size);
1765 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContextAttribsARB)(dpy, config, replay_share_context, direct, pAttrib_list);
1766 if (!replay_context)
1770 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
1771 return cStatusHardFailure;
1775 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
1783 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContextAttribsARB, pAttrib_list, attrib_list_size);
1784 VOGL_NOTE_UNUSED(pContext_state);
1788 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
1795 //----------------------------------------------------------------------------------------------------------------------
1796 // vogl_replayer::process_pending_make_current
1797 //----------------------------------------------------------------------------------------------------------------------
1798 vogl_gl_replayer::status_t vogl_gl_replayer::process_pending_make_current()
1802 if (!m_pending_make_current_packet.is_valid())
1805 vogl_trace_packet &gl_packet = m_pending_make_current_packet;
1807 Bool trace_result = gl_packet.get_return_value<Bool>();
1809 gl_entrypoint_id_t entrypoint_id = gl_packet.get_entrypoint_id();
1810 VOGL_ASSERT((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) || (entrypoint_id == VOGL_ENTRYPOINT_glXMakeContextCurrent));
1812 // pContext_state will be NULL if they are unmapping!
1813 vogl_trace_ptr_value trace_context = gl_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
1814 context_state *pContext_state = get_trace_context_state(trace_context);
1815 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
1817 if ((trace_context) && (!replay_context))
1819 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
1820 m_pending_make_current_packet.clear();
1821 return cStatusHardFailure;
1824 const Display *dpy = m_pWindow->get_display();
1825 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
1827 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
1832 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
1833 m_pending_make_current_packet.clear();
1834 return cStatusHardFailure;
1838 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
1843 m_cur_trace_context = trace_context;
1844 m_cur_replay_context = replay_context;
1845 m_pCur_context_state = pContext_state;
1849 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
1852 if (m_cur_replay_context)
1854 int viewport_x = gl_packet.get_key_value_map().get_int(string_hash("viewport_x"));
1855 int viewport_y = gl_packet.get_key_value_map().get_int(string_hash("viewport_y"));
1856 int viewport_width = gl_packet.get_key_value_map().get_int(string_hash("viewport_width"));
1857 int viewport_height = gl_packet.get_key_value_map().get_int(string_hash("viewport_height"));
1858 int win_width = gl_packet.get_key_value_map().get_int(string_hash("win_width"));
1859 int win_height = gl_packet.get_key_value_map().get_int(string_hash("win_height"));
1861 if (!m_pCur_context_state->m_has_been_made_current)
1863 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1864 viewport_x, viewport_y,
1865 viewport_width, viewport_height,
1866 win_width, win_height);
1869 GLint cur_viewport[4];
1870 GL_ENTRYPOINT(glGetIntegerv)(GL_VIEWPORT, cur_viewport);
1872 uint cur_win_width = 0, cur_win_height = 0;
1873 m_pWindow->get_actual_dimensions(cur_win_width, cur_win_height);
1875 if (!m_pCur_context_state->m_has_been_made_current)
1877 vogl_printf("glXMakeCurrent(): Replay Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
1878 cur_viewport[0], cur_viewport[1],
1879 cur_viewport[2], cur_viewport[3],
1880 cur_win_width, cur_win_height);
1883 if ((cur_viewport[0] != viewport_x) || (cur_viewport[1] != viewport_y) || (cur_viewport[2] != viewport_width) || (cur_viewport[3] != viewport_height))
1885 process_entrypoint_warning("%s: Replay viewport differs from traces!\n", VOGL_METHOD_NAME);
1888 if (!handle_context_made_current())
1889 return cStatusHardFailure;
1893 m_last_processed_call_counter = gl_packet.get_call_counter();
1895 m_pending_make_current_packet.clear();
1900 //----------------------------------------------------------------------------------------------------------------------
1901 // vogl_process_internal_trace_command_ctypes_packet
1902 //----------------------------------------------------------------------------------------------------------------------
1903 bool vogl_process_internal_trace_command_ctypes_packet(const key_value_map &kvm, const vogl_ctypes &ctypes)
1907 // TODO: Implement the code to map trace ctypes to replay ctypes. That's going to be fun.
1908 int num_trace_ctypes = kvm.get_int("num_ctypes");
1909 VOGL_VERIFY(num_trace_ctypes == VOGL_NUM_CTYPES);
1911 // TODO: This just verifies that the replayer's idea of each ctype matches the tracer's.
1912 // This will need to be revisited once we port to other OS's.
1913 // TODO: Move the ctypes crap into the SOF packet or something, it's not easy to deal with this packet on the fly.
1914 for (int ctype_iter = 0; ctype_iter < num_trace_ctypes; ctype_iter++)
1916 const vogl_ctype_desc_t &desc = ctypes[static_cast<vogl_ctype_t>(ctype_iter)];
1918 uint base_index = ctype_iter << 8;
1919 dynamic_string name(kvm.get_string(base_index++));
1920 dynamic_string ctype(kvm.get_string(base_index++));
1921 int size = kvm.get_int(base_index++);
1922 uint loki_type_flags = kvm.get_uint(base_index++);
1923 bool is_pointer = kvm.get_bool(base_index++);
1924 bool is_opaque_pointer = kvm.get_bool(base_index++);
1925 bool is_pointer_diff = kvm.get_bool(base_index++);
1926 bool is_opaque_type = kvm.get_bool(base_index++);
1928 VOGL_VERIFY(name.compare(desc.m_pName, true) == 0);
1929 VOGL_VERIFY(ctype.compare(desc.m_pCType, true) == 0);
1930 if (!desc.m_is_opaque_type)
1932 VOGL_VERIFY(size == desc.m_size);
1935 const uint loki_type_check_mask = ~(LOKI_TYPE_BITMASK(LOKI_IS_SIGNED_LONG) | LOKI_TYPE_BITMASK(LOKI_IS_UNSIGNED_LONG));
1936 VOGL_VERIFY((loki_type_flags & loki_type_check_mask) == (desc.m_loki_type_flags & loki_type_check_mask));
1938 VOGL_VERIFY(is_pointer == desc.m_is_pointer);
1939 VOGL_VERIFY(is_opaque_pointer == desc.m_is_opaque_pointer);
1940 VOGL_VERIFY(is_pointer_diff == desc.m_is_pointer_diff);
1941 VOGL_VERIFY(is_opaque_type == desc.m_is_opaque_type);
1947 //----------------------------------------------------------------------------------------------------------------------
1948 // vogl_replayer::process_internal_trace_command
1949 //----------------------------------------------------------------------------------------------------------------------
1950 vogl_gl_replayer::status_t vogl_gl_replayer::process_internal_trace_command(const vogl_trace_gl_entrypoint_packet &gl_packet)
1954 VOGL_NOTE_UNUSED(gl_packet);
1956 GLuint cmd = m_pCur_gl_packet->get_param_value<GLuint>(0);
1957 GLuint size = m_pCur_gl_packet->get_param_value<GLuint>(1);
1958 VOGL_NOTE_UNUSED(size);
1959 vogl_trace_ptr_value trace_data_ptr_value = m_pCur_gl_packet->get_param_ptr_value(2);
1960 VOGL_NOTE_UNUSED(trace_data_ptr_value);
1962 vogl_gl_replayer::status_t status = cStatusOK;
1966 case cITCRDemarcation:
1970 case cITCRKeyValueMap:
1972 const key_value_map &kvm = m_pCur_gl_packet->get_key_value_map();
1974 dynamic_string cmd_type(kvm.get_string("command_type"));
1975 if (cmd_type == "state_snapshot")
1977 dynamic_string text_id(kvm.get_string("id"));
1978 dynamic_string binary_id(kvm.get_string("binary_id"));
1979 if (text_id.is_empty() && binary_id.is_empty())
1981 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());
1982 return cStatusHardFailure;
1985 dynamic_string id_to_use(text_id.is_empty() ? binary_id : text_id);
1987 // TODO: Make a 1st class snapshot cache class
1988 // TODO: This could fail if the user hand modifies the snapshot in some way - add an option to disable caching.
1989 vogl_gl_state_snapshot *pSnapshot = NULL;
1990 if (m_flags & cGLReplayerSnapshotCaching)
1992 for (uint snapshot_index = 0; snapshot_index < m_snapshots.size(); snapshot_index++)
1994 if (!m_snapshots[snapshot_index].m_name.compare(id_to_use, false))
1996 pSnapshot = m_snapshots[snapshot_index].m_pSnapshot;
1999 snapshot_cache_entry cache_entry(m_snapshots[snapshot_index]);
2000 m_snapshots.erase(snapshot_index);
2001 m_snapshots.insert(0, cache_entry);
2010 timed_scope ts("Deserialize snapshot time");
2012 if (!m_pBlob_manager)
2014 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2015 return cStatusHardFailure;
2018 uint8_vec snapshot_data;
2020 if (!m_pBlob_manager->get(id_to_use, snapshot_data) || (snapshot_data.is_empty()))
2022 process_entrypoint_error("%s: Failed reading snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2023 return cStatusHardFailure;
2026 vogl_message_printf("%s: Deserializing state snapshot \"%s\", %u bytes\n", VOGL_METHOD_NAME, id_to_use.get_ptr(), snapshot_data.size());
2031 if (id_to_use == text_id)
2032 success = doc.deserialize(reinterpret_cast<const char *>(snapshot_data.get_ptr()), snapshot_data.size());
2034 success = doc.binary_deserialize(snapshot_data);
2035 if (!success || (!doc.get_root()))
2037 process_entrypoint_error("%s: Failed deserializing JSON snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2038 return cStatusHardFailure;
2041 pSnapshot = vogl_new(vogl_gl_state_snapshot);
2042 if (!pSnapshot->deserialize(*doc.get_root(), *m_pBlob_manager, &m_trace_gl_ctypes))
2044 vogl_delete(pSnapshot);
2047 process_entrypoint_error("%s: Failed deserializing snapshot blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2048 return cStatusHardFailure;
2051 if (m_flags & cGLReplayerSnapshotCaching)
2053 snapshot_cache_entry new_cache_entry;
2054 new_cache_entry.m_name = id_to_use;
2055 new_cache_entry.m_pSnapshot = pSnapshot;
2056 m_snapshots.insert(0, new_cache_entry);
2058 // FIXME: Even 3-4 snapshots in memory may be too much in 32-bit mode for some large apps.
2059 while (m_snapshots.size() > 3)
2061 vogl_delete(m_snapshots.back().m_pSnapshot);
2062 m_snapshots.resize(m_snapshots.size() - 1);
2067 status = begin_applying_snapshot(pSnapshot, (m_flags & cGLReplayerSnapshotCaching) ? false : true);
2069 if ((status != cStatusOK) && (status != cStatusResizeWindow))
2071 if (m_flags & cGLReplayerSnapshotCaching)
2073 VOGL_ASSERT(m_snapshots[0].m_pSnapshot == pSnapshot);
2075 vogl_delete(m_snapshots[0].m_pSnapshot);
2076 m_snapshots.erase(0U);
2079 if (m_flags & cGLReplayerSnapshotCaching)
2081 vogl_delete(pSnapshot);
2085 process_entrypoint_error("%s: Failed applying GL snapshot from blob data \"%s\"!\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2089 vogl_message_printf("%s: Successfully applied GL state snapshot from blob \"%s\"\n", VOGL_METHOD_NAME, id_to_use.get_ptr());
2091 else if (cmd_type == "ctypes")
2093 m_ctypes_packet = *m_pCur_gl_packet;
2095 if (!vogl_process_internal_trace_command_ctypes_packet(kvm, m_trace_gl_ctypes))
2096 return cStatusHardFailure;
2098 else if (cmd_type == "entrypoints")
2104 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD key_value_map command type: \"%s\"\n", VOGL_METHOD_NAME, cmd_type.get_ptr());
2110 process_entrypoint_warning("%s: Unknown glInternalTraceCommandRAD command type: %u\n", VOGL_METHOD_NAME, cmd);
2118 //----------------------------------------------------------------------------------------------------------------------
2119 // vogl_replayer::check_program_binding_shadow
2120 //----------------------------------------------------------------------------------------------------------------------
2121 bool vogl_gl_replayer::check_program_binding_shadow()
2125 if (!m_pCur_context_state)
2128 // Make sure shadow is good
2129 GLint actual_current_replay_program = 0;
2130 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
2133 if (m_pCur_context_state->m_cur_replay_program == static_cast<GLuint>(actual_current_replay_program))
2136 // OK, on AMD it plays games with GL_CURRENT_PROGRAM when the currently bound program is deleted. Check for this scenario.
2137 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(m_pCur_context_state->m_cur_replay_program) != 0;
2138 if ((!check_gl_error()) && (is_still_program))
2140 GLint marked_for_deletion = GL_FALSE;
2141 GL_ENTRYPOINT(glGetProgramiv)(m_pCur_context_state->m_cur_replay_program, GL_DELETE_STATUS, &marked_for_deletion);
2143 if ((!check_gl_error()) && (marked_for_deletion))
2151 //----------------------------------------------------------------------------------------------------------------------
2152 // vogl_replayer::handle_use_program
2153 //----------------------------------------------------------------------------------------------------------------------
2154 void vogl_gl_replayer::handle_use_program(GLuint trace_handle, gl_entrypoint_id_t entrypoint_id)
2158 // 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.
2159 check_program_binding_shadow();
2161 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2162 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2163 VOGL_ASSERT(!trace_handle || get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2165 // For safety, absorb any previous error.
2168 GLuint prev_replay_program = m_pCur_context_state->m_cur_replay_program;
2169 GLuint prev_trace_program = m_pCur_context_state->m_cur_trace_program;
2171 bool prev_is_program = false;
2172 GLint prev_link_status = false;
2173 GLint prev_is_marked_for_deletion = false;
2174 vogl::growable_array<GLuint, 8> prev_attached_replay_shaders;
2176 if ((prev_replay_program) && (replay_handle != prev_replay_program))
2178 prev_is_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2179 check_gl_error_quietly();
2181 if (prev_is_program)
2183 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_DELETE_STATUS, &prev_is_marked_for_deletion);
2184 check_gl_error_quietly();
2186 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_LINK_STATUS, &prev_link_status);
2187 check_gl_error_quietly();
2189 if (prev_is_marked_for_deletion)
2191 // 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.
2192 GLint num_attached_shaders = 0;
2193 GL_ENTRYPOINT(glGetProgramiv)(prev_replay_program, GL_ATTACHED_SHADERS, &num_attached_shaders);
2194 check_gl_error_quietly();
2196 if (num_attached_shaders)
2198 prev_attached_replay_shaders.resize(num_attached_shaders);
2200 GLsizei actual_count = 0;
2201 GL_ENTRYPOINT(glGetAttachedShaders)(prev_replay_program, num_attached_shaders, &actual_count, prev_attached_replay_shaders.get_ptr());
2202 check_gl_error_quietly();
2204 VOGL_ASSERT(actual_count == num_attached_shaders);
2210 if (entrypoint_id == VOGL_ENTRYPOINT_glUseProgram)
2211 GL_ENTRYPOINT(glUseProgram)(replay_handle);
2213 GL_ENTRYPOINT(glUseProgramObjectARB)(replay_handle);
2215 // Can't shadow if glUseProgram failed.
2216 if (check_gl_error())
2219 if ((prev_replay_program) && (prev_replay_program != replay_handle))
2221 bool is_prev_still_program = GL_ENTRYPOINT(glIsProgram)(prev_replay_program);
2222 if (!is_prev_still_program)
2224 VOGL_ASSERT(prev_is_program);
2225 VOGL_ASSERT(prev_is_marked_for_deletion);
2227 // The previously bound program is really dead now, kill it from our tables and also check up on any shaders it was attached to.
2228 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(prev_trace_program);
2229 VOGL_ASSERT(was_deleted);
2230 VOGL_NOTE_UNUSED(was_deleted);
2232 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(prev_trace_program);
2233 VOGL_ASSERT(was_deleted);
2235 was_deleted = get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(prev_replay_program);
2236 if ((prev_link_status) && (!was_deleted))
2241 for (uint i = 0; i < prev_attached_replay_shaders.size(); i++)
2243 GLuint replay_shader_handle = prev_attached_replay_shaders[i];
2245 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle);
2246 check_gl_error_quietly();
2248 if (is_still_shader)
2251 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2253 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2257 // The attached shader is now really dead.
2258 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2259 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2261 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);
2267 m_pCur_context_state->m_cur_replay_program = replay_handle;
2268 m_pCur_context_state->m_cur_trace_program = trace_handle;
2271 //----------------------------------------------------------------------------------------------------------------------
2272 // vogl_replayer::handle_delete_program
2273 //----------------------------------------------------------------------------------------------------------------------
2274 void vogl_gl_replayer::handle_delete_program(GLuint trace_handle)
2278 check_program_binding_shadow();
2280 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2282 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2283 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_PROGRAM_OBJECT);
2284 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_PROGRAM_OBJECT);
2286 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
2287 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
2289 if (it->first == m_pCur_context_state->m_context_desc.get_trace_context())
2292 context_state *pContext = it->second;
2293 if (pContext->m_pShared_state == pContext_shareroot)
2295 if (pContext->m_cur_trace_program == trace_handle)
2297 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",
2298 VOGL_METHOD_NAME, trace_handle, replay_handle,
2299 cast_val_to_uint64(m_pCur_context_state->m_context_desc.get_trace_context()),
2300 cast_val_to_uint64(it->first));
2305 bool is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2306 check_gl_error_quietly();
2308 vogl::growable_array<GLuint, 8> attached_replay_shaders;
2310 if ((is_program) && (replay_handle))
2312 GLint num_attached_shaders = 0;
2313 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ATTACHED_SHADERS, &num_attached_shaders);
2314 check_gl_error_quietly();
2316 if (num_attached_shaders)
2318 attached_replay_shaders.resize(num_attached_shaders);
2320 GLsizei actual_count = 0;
2321 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, num_attached_shaders, &actual_count, attached_replay_shaders.get_ptr());
2322 check_gl_error_quietly();
2324 VOGL_ASSERT(actual_count == num_attached_shaders);
2328 GL_ENTRYPOINT(glDeleteProgram)(replay_handle);
2330 bool deletion_succeeded = !check_gl_error();
2331 if (!deletion_succeeded)
2333 VOGL_ASSERT(!is_program);
2335 process_entrypoint_warning("%s: Failed deleting program, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2342 bool is_still_program = GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0;
2343 check_gl_error_quietly();
2345 GLint marked_for_deletion = 0;
2346 if (is_still_program)
2348 // It must still be bound to the context, or referred to in some other way that we don't know about.
2349 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2350 bool delete_status_check_succeeded = !check_gl_error_quietly();
2352 VOGL_VERIFY(delete_status_check_succeeded);
2353 VOGL_VERIFY(marked_for_deletion);
2355 else if (!is_still_program)
2357 VOGL_ASSERT(is_program);
2359 // The program is really gone now.
2360 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2361 VOGL_ASSERT(was_deleted);
2362 VOGL_NOTE_UNUSED(was_deleted);
2364 was_deleted = get_shared_state()->m_glsl_program_hash_map.erase(trace_handle);
2365 VOGL_ASSERT(was_deleted);
2367 get_shared_state()->m_shadow_state.m_linked_programs.remove_snapshot(replay_handle);
2369 if (m_pCur_context_state->m_cur_replay_program == replay_handle)
2371 // This shouldn't happen - if the program is still bound to the context then it should still be a program.
2373 m_pCur_context_state->m_cur_replay_program = 0;
2374 m_pCur_context_state->m_cur_trace_program = 0;
2377 for (uint i = 0; i < attached_replay_shaders.size(); i++)
2379 GLuint replay_shader_handle = attached_replay_shaders[i];
2381 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_shader_handle) != 0;
2382 check_gl_error_quietly();
2384 if (is_still_shader)
2387 if (!get_shared_state()->m_shadow_state.m_objs.contains_inv(replay_shader_handle))
2389 // We didn't create this shader handle, the AMD driver did on a program binary link, so ignore it.
2393 // The attached shader is now really dead.
2394 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_shader_handle) == VOGL_SHADER_OBJECT);
2395 if (!get_shared_state()->m_shadow_state.m_objs.erase_inv(replay_shader_handle))
2397 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);
2403 //----------------------------------------------------------------------------------------------------------------------
2404 // vogl_replayer::handle_delete_shader
2405 //----------------------------------------------------------------------------------------------------------------------
2406 void vogl_gl_replayer::handle_delete_shader(GLuint trace_handle)
2410 check_program_binding_shadow();
2414 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2416 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2417 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle) == VOGL_SHADER_OBJECT);
2418 VOGL_ASSERT(get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle) == VOGL_SHADER_OBJECT);
2420 GL_ENTRYPOINT(glDeleteShader)(replay_handle);
2422 bool deletion_succeeded = !check_gl_error();
2423 if (!deletion_succeeded)
2425 process_entrypoint_warning("%s: Failed deleting shader, trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
2432 bool is_still_shader = GL_ENTRYPOINT(glIsShader)(replay_handle);
2433 check_gl_error_quietly();
2435 if (!is_still_shader)
2437 // The shader is really gone.
2438 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_handle);
2439 VOGL_ASSERT(was_deleted);
2440 VOGL_NOTE_UNUSED(was_deleted);
2444 GLint marked_for_deletion = 0;
2445 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, GL_DELETE_STATUS, &marked_for_deletion);
2446 check_gl_error_quietly();
2448 VOGL_VERIFY(marked_for_deletion);
2450 // The shader is attached to a live program object (which may or may not be actually in the marked_as_deleted state)
2451 // we'll get around to it when the program object is deleted, or when they remove the program object from the current state.
2455 //----------------------------------------------------------------------------------------------------------------------
2456 // vogl_replayer::handle_detach_shader
2457 //----------------------------------------------------------------------------------------------------------------------
2458 void vogl_gl_replayer::handle_detach_shader(gl_entrypoint_id_t entrypoint_id)
2460 GLuint trace_program = m_pCur_gl_packet->get_param_value<GLuint>(0);
2461 GLuint replay_program = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_program);
2463 GLuint trace_shader = m_pCur_gl_packet->get_param_value<GLuint>(1);
2464 GLuint replay_shader = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_shader);
2468 // Note: This mixes ARB and non-ARB funcs. to probe around, which is evil.
2470 GLboolean was_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2471 check_gl_error_quietly();
2473 GLint marked_for_deletion = 0;
2474 GL_ENTRYPOINT(glGetShaderiv)(replay_shader, GL_DELETE_STATUS, &marked_for_deletion);
2475 check_gl_error_quietly();
2477 if (entrypoint_id == VOGL_ENTRYPOINT_glDetachObjectARB)
2478 GL_ENTRYPOINT(glDetachObjectARB)(replay_program, replay_shader);
2481 VOGL_ASSERT(entrypoint_id == VOGL_ENTRYPOINT_glDetachShader);
2482 GL_ENTRYPOINT(glDetachShader)(replay_program, replay_shader);
2485 bool detach_failed = check_gl_error();
2487 GLboolean is_shader = GL_ENTRYPOINT(glIsShader)(replay_shader);
2488 check_gl_error_quietly();
2492 if ((marked_for_deletion) && (was_shader) && (!is_shader))
2494 // The shader is really gone now.
2495 bool was_deleted = get_shared_state()->m_shadow_state.m_objs.erase(trace_shader);
2496 VOGL_ASSERT(was_deleted);
2497 VOGL_NOTE_UNUSED(was_deleted);
2502 //----------------------------------------------------------------------------------------------------------------------
2503 // vogl_gl_replayer::handle_link_program
2504 //----------------------------------------------------------------------------------------------------------------------
2505 void vogl_gl_replayer::handle_link_program(gl_entrypoint_id_t entrypoint_id)
2509 GLuint trace_handle = m_pCur_gl_packet->get_param_value<GLuint>(0);
2510 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
2512 GLboolean is_program = GL_ENTRYPOINT(glIsProgram)(replay_handle);
2516 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);
2519 const json_document *pDoc = m_pCur_gl_packet->get_key_value_map().get_json_document("metadata");
2523 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);
2525 else if ((pDoc) && (!pDoc->is_object()))
2527 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);
2531 int trace_active_attributes = 0;
2532 int trace_active_uniforms = 0;
2533 int trace_active_uniform_blocks = 0;
2534 int trace_link_status = 1;
2536 VOGL_NOTE_UNUSED(trace_active_uniforms);
2537 VOGL_NOTE_UNUSED(trace_active_uniform_blocks);
2541 const json_node &doc_root = *pDoc->get_root();
2543 trace_link_status = doc_root.value_as_int("link_status");
2544 trace_active_attributes = doc_root.value_as_int("total_active_attributes");
2545 trace_active_uniforms = doc_root.value_as_int("total_active_uniforms");
2546 trace_active_uniform_blocks = doc_root.value_as_int("active_uniform_blocks");
2548 const json_node *pAttrib_node = doc_root.find_child_array("active_attribs");
2551 for (uint i = 0; i < pAttrib_node->size(); i++)
2553 const json_node *pAttrib = pAttrib_node->get_child(i);
2560 const char *pName = pAttrib->value_as_string_ptr("name");
2561 int attrib_loc = pAttrib->value_as_int("location", -1);
2563 if ((pName) && (pName[0]) && (attrib_loc >= 0))
2565 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2566 GL_ENTRYPOINT(glBindAttribLocationARB)(replay_handle, attrib_loc, pName);
2568 GL_ENTRYPOINT(glBindAttribLocation)(replay_handle, attrib_loc, reinterpret_cast<const GLchar *>(pName));
2575 const json_node *pOutputs_object = doc_root.find_child_array("active_outputs");
2576 if (pOutputs_object)
2578 for (uint i = 0; i < pOutputs_object->size(); i++)
2580 const json_node *pOutput_node = pOutputs_object->get_child(i);
2584 dynamic_string name(pOutput_node->value_as_string("name"));
2585 if ((name.is_empty()) || (name.begins_with("gl_", true)))
2588 int location = pOutput_node->value_as_int("location");
2589 int location_index = pOutput_node->value_as_int("location_index");
2591 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_blend_func_extended") && GL_ENTRYPOINT(glBindFragDataLocationIndexed))
2593 GL_ENTRYPOINT(glBindFragDataLocationIndexed)(replay_handle, location, location_index, reinterpret_cast<const GLchar *>(name.get_ptr()));
2598 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);
2600 GL_ENTRYPOINT(glBindFragDataLocation)(replay_handle, location, reinterpret_cast<const GLchar *>(name.get_ptr()));
2607 GLenum transform_feedback_mode = vogl_get_json_value_as_enum(doc_root, "transform_feedback_mode");
2608 GLint num_varyings = doc_root.value_as_int("transform_feedback_num_varyings");
2611 const json_node *pTransform_feedback_varyings = doc_root.find_child_array("transform_feedback_varyings");
2612 if (pTransform_feedback_varyings)
2614 dynamic_string_array names;
2616 for (uint i = 0; i < pTransform_feedback_varyings->size(); i++)
2618 const json_node *pVarying_node = pTransform_feedback_varyings->get_child(i);
2622 GLint index = pVarying_node->value_as_int("index");
2626 dynamic_string name(pVarying_node->value_as_string("name"));
2628 //GLsizei size(pVarying_node->value_as_int("size"));
2629 //GLenum type(vogl_get_json_value_as_enum(*pVarying_node, "type"));
2631 names.ensure_element_is_valid(index);
2632 names[index] = name;
2635 vogl::vector<GLchar *> varyings(names.size());
2636 for (uint i = 0; i < names.size(); i++)
2637 varyings[i] = (GLchar *)(names[i].get_ptr());
2639 GL_ENTRYPOINT(glTransformFeedbackVaryings)(replay_handle, varyings.size(), varyings.get_ptr(), transform_feedback_mode);
2645 switch (entrypoint_id)
2647 case VOGL_ENTRYPOINT_glLinkProgram:
2649 GL_ENTRYPOINT(glLinkProgram)(replay_handle);
2652 case VOGL_ENTRYPOINT_glLinkProgramARB:
2654 GL_ENTRYPOINT(glLinkProgramARB)(replay_handle);
2657 case VOGL_ENTRYPOINT_glProgramBinary:
2659 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));
2671 GLint replay_link_status = 0;
2672 GLint replay_active_attributes = 0;
2673 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2675 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_LINK_STATUS_ARB, &replay_link_status);
2678 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &replay_active_attributes);
2683 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_LINK_STATUS, &replay_link_status);
2686 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_ACTIVE_ATTRIBUTES, &replay_active_attributes);
2690 if ((replay_link_status) || (!get_shared_state()->m_shadow_state.m_linked_programs.find_snapshot(replay_handle)))
2693 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramBinary)
2694 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));
2696 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);
2699 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);
2702 if ((pDoc) && (replay_link_status != trace_link_status))
2704 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);
2707 if (!replay_link_status)
2709 vogl::vector<GLchar> log;
2711 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2714 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
2721 GLint actual_length = 0;
2722 GL_ENTRYPOINT(glGetInfoLogARB)(replay_handle, log.size(), &actual_length, reinterpret_cast<GLcharARB *>(log.get_ptr()));
2729 GL_ENTRYPOINT(glGetProgramiv)(replay_handle, GL_INFO_LOG_LENGTH, &length);
2736 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, log.size(), &length, log.get_ptr());
2741 if ((log.size()) && (log[0]))
2743 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());
2747 if ((pDoc) && (replay_active_attributes != trace_active_attributes))
2749 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);
2752 const json_node *pUniforms_node = pDoc ? pDoc->get_root()->find_child_array("active_uniforms") : NULL;
2756 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
2757 if (it == get_shared_state()->m_glsl_program_hash_map.end())
2758 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
2759 glsl_program_state &prog_state = it->second;
2761 for (uint i = 0; i < pUniforms_node->size(); i++)
2763 const json_node *pUniform = pUniforms_node->get_child(i);
2770 const char *pName = pUniform->value_as_string_ptr("name");
2776 int trace_loc = pUniform->value_as_int("location");
2777 int trace_array_size = pUniform->value_as_int("size");
2778 //int trace_type = pUniform->value_as_int("type");
2780 VOGL_ASSERT(trace_array_size >= 1);
2782 if ((trace_loc < 0) || (trace_array_size <= 0))
2785 if (trace_array_size > 1)
2787 dynamic_string element_name;
2788 for (int i = 0; i < trace_array_size; i++)
2790 element_name = pName;
2791 int start_bracket_ofs = element_name.find_right('[');
2792 if (start_bracket_ofs >= 0)
2793 element_name.left(start_bracket_ofs);
2794 element_name.format_append("[%u]", i);
2796 GLint element_trace_loc = trace_loc + i;
2797 GLint element_replay_loc;
2798 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2799 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(element_name.get_ptr()));
2801 element_replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(element_name.get_ptr()));
2804 if (element_replay_loc < 0)
2806 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);
2810 prog_state.m_uniform_locations.erase(element_trace_loc);
2811 prog_state.m_uniform_locations.insert(element_trace_loc, element_replay_loc);
2815 else if (trace_array_size == 1)
2818 if (entrypoint_id == VOGL_ENTRYPOINT_glLinkProgramARB)
2819 replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, reinterpret_cast<const GLcharARB *>(pName));
2821 replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, reinterpret_cast<const GLchar *>(pName));
2826 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);
2830 prog_state.m_uniform_locations.erase(trace_loc);
2831 prog_state.m_uniform_locations.insert(trace_loc, replay_loc);
2838 //----------------------------------------------------------------------------------------------------------------------
2839 // vogl_gl_replayer::post_draw_call
2840 // Called after each draw call or blit.
2841 //----------------------------------------------------------------------------------------------------------------------
2842 vogl_gl_replayer::status_t vogl_gl_replayer::post_draw_call()
2846 if (m_pCur_context_state->m_inside_gl_begin)
2849 if (check_gl_error())
2850 return cStatusGLError;
2852 bool is_draw = vogl_is_draw_entrypoint(m_pCur_gl_packet->get_entrypoint_id());
2854 if ((m_flags & cGLReplayerDumpShadersOnDraw) && (is_draw))
2856 dump_current_shaders();
2859 if (m_flags & cGLReplayerDumpFramebufferOnDraws)
2861 bool should_dump = false;
2863 if (m_dump_framebuffer_on_draw_frame_index != -1)
2865 if (m_frame_index == m_dump_framebuffer_on_draw_frame_index)
2868 else if ((m_dump_framebuffer_on_draw_first_gl_call_index >= 0) && (m_dump_framebuffer_on_draw_last_gl_call_index >= 0))
2870 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);
2879 dump_current_framebuffer();
2883 m_frame_draw_counter += is_draw;
2888 //----------------------------------------------------------------------------------------------------------------------
2889 // vogl_gl_replayer::dump_framebuffer
2890 //----------------------------------------------------------------------------------------------------------------------
2891 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)
2895 uint trace_read_framebuffer = 0;
2896 if (read_framebuffer)
2898 gl_handle_hash_map::const_iterator it = get_context_state()->m_framebuffers.search_table_for_value(read_framebuffer);
2899 if (it != get_context_state()->m_framebuffers.end())
2900 trace_read_framebuffer = it->second;
2903 uint trace_texture = replay_texture;
2906 if (!get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_texture, trace_texture))
2907 vogl_warning_printf("%s: Failed finding GL handle %u in texture handle shadow!\n", VOGL_METHOD_NAME, replay_texture);
2913 if (!get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_rbo, trace_rbo))
2914 vogl_error_printf("%s: Failed finding GL handle %u in RBO handle shadow!\n", VOGL_METHOD_NAME, replay_rbo);
2917 m_screenshot_buffer.resize(width * height * 3);
2919 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);
2923 process_entrypoint_warning("%s: vogl_copy_buffer_to_image() failed!\n", VOGL_METHOD_NAME);
2927 size_t png_size = 0;
2928 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
2930 dynamic_string screenshot_filename(cVarArg, "%s_GLCTR%08llu_%s_FR%06u_DCTR%05llu_W%04i_H%04i_FBO%04u_%s",
2931 m_dump_framebuffer_on_draw_prefix.get_ptr(),
2932 (unsigned long long)m_pCur_gl_packet->get_call_counter(),
2933 g_vogl_entrypoint_descs[m_pCur_gl_packet->get_entrypoint_id()].m_pName,
2935 (unsigned long long)m_frame_draw_counter,
2937 trace_read_framebuffer,
2938 g_gl_enums.find_gl_name(read_buffer));
2940 if (internal_format != GL_NONE)
2942 screenshot_filename += "_";
2943 screenshot_filename += g_gl_enums.find_gl_image_format_name(internal_format);
2946 if (orig_samples != 0)
2947 screenshot_filename += dynamic_string(cVarArg, "_MSAA%u", orig_samples);
2949 screenshot_filename += dynamic_string(cVarArg, "_TEX%04u", replay_texture);
2951 screenshot_filename += dynamic_string(cVarArg, "_RBO%04u", replay_rbo);
2953 screenshot_filename += ".png";
2955 file_utils::create_directories(file_utils::get_pathname(screenshot_filename.get_ptr()), false);
2957 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
2959 process_entrypoint_error("%s: Failed writing framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2964 vogl_printf("%s: Wrote framebuffer screenshot to file \"%s\"\n", VOGL_METHOD_NAME, screenshot_filename.get_ptr());
2972 //----------------------------------------------------------------------------------------------------------------------
2973 // vogl_gl_replayer::dump_current_framebuffer
2974 //----------------------------------------------------------------------------------------------------------------------
2975 void vogl_gl_replayer::dump_current_framebuffer()
2979 uint draw_framebuffer_binding = vogl_get_gl_integer(GL_DRAW_FRAMEBUFFER_BINDING);
2981 uint max_draw_buffers = vogl_get_gl_integer(GL_MAX_DRAW_BUFFERS);
2982 if (!max_draw_buffers)
2984 process_entrypoint_warning("%s: GL_MAX_DRAW_BUFFERS is 0\n", VOGL_METHOD_NAME);
2988 //GL_COLOR_ATTACHMENT0-GL_COLOR_ATTACHMENT15, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT
2990 vogl::vector<GLenum> draw_buffers(max_draw_buffers);
2991 for (uint i = 0; i < max_draw_buffers; i++)
2992 draw_buffers[i] = vogl_get_gl_integer(GL_DRAW_BUFFER0 + i);
2994 if (!draw_framebuffer_binding)
2996 for (uint i = 0; i < max_draw_buffers; i++)
2997 if (draw_buffers[i] != GL_NONE)
2998 dump_framebuffer(m_pWindow->get_width(), m_pWindow->get_height(), 0, draw_buffers[i], GL_NONE, 0, 0, 0);
3002 // TODO: We should probably keep around a persistent set of per-context (or sharelist) remappers
3003 vogl_framebuffer_state fbo_state;
3004 if (!fbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, draw_framebuffer_binding, GL_NONE))
3006 process_entrypoint_warning("%s: Unable to snapshot current FBO %u\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3010 for (uint i = 0; i < draw_buffers.size(); i++)
3012 if (draw_buffers[i] == GL_NONE)
3015 const vogl_framebuffer_attachment *pAttachment = fbo_state.get_attachments().find_value(draw_buffers[i]);
3018 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);
3022 if (pAttachment->get_type() == GL_FRAMEBUFFER_DEFAULT)
3024 else if (pAttachment->get_type() == GL_RENDERBUFFER)
3026 GLuint rbo_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3030 vogl_renderbuffer_state rbo_state;
3031 if (!rbo_state.snapshot(m_pCur_context_state->m_context_info, m_replay_to_trace_remapper, rbo_handle, GL_NONE))
3033 process_entrypoint_warning("%s: Failed getting RBO %u's' state!\n", VOGL_METHOD_NAME, rbo_handle);
3037 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))
3040 uint width = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_WIDTH);
3041 uint height = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_HEIGHT);
3042 uint samples = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_SAMPLES);
3043 GLenum internal_format = rbo_state.get_desc().get_int_or_default(GL_RENDERBUFFER_INTERNAL_FORMAT);
3045 if ((!width) || (!height) || (!internal_format))
3047 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);
3053 vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER);
3055 GLuint temp_rbo = 0;
3056 GL_ENTRYPOINT(glGenRenderbuffers)(1, &temp_rbo);
3062 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, temp_rbo);
3065 GL_ENTRYPOINT(glRenderbufferStorage)(GL_RENDERBUFFER, internal_format, width, height);
3068 GLuint temp_fbo = 0;
3069 GL_ENTRYPOINT(glGenFramebuffers)(1, &temp_fbo);
3072 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, temp_fbo);
3075 GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, temp_rbo);
3078 GLenum draw_buf = GL_COLOR_ATTACHMENT0;
3079 GL_ENTRYPOINT(glDrawBuffers)(1, &draw_buf);
3082 GL_ENTRYPOINT(glReadBuffer)(GL_NONE);
3085 GLenum cur_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
3088 if (cur_status == GL_FRAMEBUFFER_COMPLETE)
3090 GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, draw_framebuffer_binding);
3093 // Save the framebuffer's readbuffer (it's per-framebuffer state, not context state).
3094 vogl_scoped_state_saver state_saver(cGSTReadBuffer);
3096 GL_ENTRYPOINT(glReadBuffer)(draw_buffers[i]);
3099 GL_ENTRYPOINT(glBlitFramebuffer)(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3101 if (!check_gl_error())
3102 dump_framebuffer(width, height, temp_fbo, GL_COLOR_ATTACHMENT0, internal_format, samples, 0, rbo_handle);
3105 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);
3109 GL_ENTRYPOINT(glBindRenderbuffer)(GL_RENDERBUFFER, 0);
3112 GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
3115 GL_ENTRYPOINT(glDeleteFramebuffers)(1, &temp_fbo);
3118 GL_ENTRYPOINT(glDeleteRenderbuffers)(1, &temp_rbo);
3123 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, 0, rbo_handle);
3126 else if (pAttachment->get_type() == GL_TEXTURE)
3128 GLuint tex_handle = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
3131 process_entrypoint_warning("%s: Current FBO %u has a invalid object name\n", VOGL_METHOD_NAME, draw_framebuffer_binding);
3135 GLenum target = get_shared_state()->m_shadow_state.m_textures.get_target_inv(tex_handle);
3136 if (target == GL_NONE)
3138 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);
3142 if ((target == GL_TEXTURE_CUBE_MAP) || (target == GL_TEXTURE_CUBE_MAP_ARRAY))
3143 target = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
3145 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))
3147 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);
3151 uint level = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
3152 uint layer = pAttachment->get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
3153 VOGL_NOTE_UNUSED(layer);
3155 GLint width = 0, height = 0, samples = 0;
3156 GLenum internal_format = GL_NONE;
3159 vogl_scoped_binding_state binding_saver;
3160 binding_saver.save_textures();
3162 GL_ENTRYPOINT(glBindTexture)(target, tex_handle);
3165 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_WIDTH, &width);
3168 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_HEIGHT, &height);
3171 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<GLint *>(&internal_format));
3174 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_texture_multisample"))
3176 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, GL_TEXTURE_SAMPLES, &samples);
3181 if ((!width) || (!height))
3183 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);
3189 process_entrypoint_warning("%s: Can't dump multisample texture FBO attachments yet\n", VOGL_METHOD_NAME);
3193 dump_framebuffer(width, height, draw_framebuffer_binding, draw_buffers[i], internal_format, 0, tex_handle, 0);
3198 //----------------------------------------------------------------------------------------------------------------------
3199 // vogl_gl_replayer::dump_current_shaders
3200 //----------------------------------------------------------------------------------------------------------------------
3201 void vogl_gl_replayer::dump_current_shaders()
3205 if (!m_pCur_context_state)
3210 const GLuint replay_program = m_pCur_context_state->m_cur_replay_program;
3212 // Get the current program.
3213 GLuint current_program = 0;
3214 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, (GLint *)(¤t_program));
3217 VOGL_ASSERT(replay_program == current_program);
3219 if (!current_program)
3222 // Get the attached shaders.
3223 GLsizei attached_shader_count = -1;
3224 GL_ENTRYPOINT(glGetProgramiv)(replay_program, GL_ATTACHED_SHADERS, &attached_shader_count);
3227 if (!attached_shader_count)
3230 vogl::vector<GLuint> shaders(attached_shader_count);
3231 GLsizei actual_shader_count = 0;
3232 GL_ENTRYPOINT(glGetAttachedShaders)(replay_program,
3233 attached_shader_count,
3234 &actual_shader_count,
3238 VOGL_ASSERT(attached_shader_count == actual_shader_count); // Sanity check.
3240 vogl_printf("Trace context 0x%" PRIx64 ", GL draw counter %" PRIu64 ", frame %u, replay program %u trace program %u has %d attached shaders:\n",
3241 cast_val_to_uint64(m_cur_trace_context), m_last_parsed_call_counter, m_frame_index,
3242 replay_program, m_pCur_context_state->m_cur_trace_program,
3243 attached_shader_count);
3245 // Get source from shaders.
3246 vogl::vector<GLchar> source; // Shared buffer for each iteration.
3247 for (GLsizei i = 0; i < attached_shader_count; ++i)
3249 const GLuint shader = shaders[i];
3250 GLint shader_type = 0;
3251 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_TYPE, &shader_type);
3254 vogl_printf("\n%s: %u\n", g_gl_enums.find_gl_name(shader_type), shader);
3256 GLint source_length = -1; // Includes NUL terminator.
3257 GL_ENTRYPOINT(glGetShaderiv)(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
3260 VOGL_ASSERT(source_length > 0);
3262 source.resize(source_length);
3263 GLint actual_length = 0; // Excludes NUL terminator!
3264 GL_ENTRYPOINT(glGetShaderSource)(shader, source_length, &actual_length, source.get_ptr());
3267 VOGL_ASSERT(source_length == actual_length + 1); // Sanity check.
3268 vogl_printf("%.*s\n", source_length, source.get_const_ptr());
3270 vogl_printf("========\n");
3273 //----------------------------------------------------------------------------------------------------------------------
3274 // vogl_gl_replayer::handle_ShaderSource
3275 // Handle ShaderSource and ShaderSourceARB.
3276 //----------------------------------------------------------------------------------------------------------------------
3277 vogl_gl_replayer::status_t vogl_gl_replayer::handle_ShaderSource(GLhandleARB trace_object,
3279 const vogl_client_memory_array trace_strings_glchar_ptr_array,
3280 const GLint *pTrace_lengths)
3284 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
3286 // m_pCur_gl_packet->get_param_client_memory_data_size(2) / sizeof(const GLchar *);
3287 const uint trace_strings_count = trace_strings_glchar_ptr_array.size();
3288 const uint trace_lengths_count = m_pCur_gl_packet->get_param_client_memory_data_size(3) / sizeof(const GLint);
3290 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3291 (trace_strings_count != static_cast<uint>(count)))
3293 process_entrypoint_error("%s: Trace strings array has an invalid count (expected %u, got %u)\n",
3294 VOGL_METHOD_NAME, count, trace_strings_count);
3295 return cStatusHardFailure;
3298 if ((pTrace_lengths) && (trace_lengths_count != static_cast<uint>(count)))
3300 process_entrypoint_error("%s: Trace lengths array has an invalid count (expected %u, got %u)\n",
3301 VOGL_METHOD_NAME, count, trace_lengths_count);
3302 return cStatusHardFailure;
3305 vogl::vector<const GLcharARB *> strings(count);
3306 vogl::vector<GLint> lengths(count);
3308 const key_value_map &map = m_pCur_gl_packet->get_key_value_map();
3310 vogl::vector<uint8_vec> blobs(count);
3312 for (GLsizei i = 0; i < count; i++)
3315 if ((trace_strings_glchar_ptr_array.get_ptr()) &&
3316 (trace_strings_glchar_ptr_array.get_element<vogl_trace_ptr_value>(i) != 0))
3321 lengths[i] = pTrace_lengths ? pTrace_lengths[i] : 0;
3323 key_value_map::const_iterator it = map.find(i);
3324 if (it == map.end())
3328 process_entrypoint_error("%s: Failed finding blob for non-empty string %i in packet's key value map\n",
3329 VOGL_METHOD_NAME, i);
3330 return cStatusHardFailure;
3335 const uint8_vec *pBlob = it->second.get_blob();
3338 process_entrypoint_error("%s: Can't convert string %i to a blob\n", VOGL_METHOD_NAME, i);
3339 return cStatusHardFailure;
3343 uint8_vec &blob = blobs[i];
3345 if ((pTrace_lengths) && (pTrace_lengths[i] >= 0))
3347 if (static_cast<uint>(pTrace_lengths[i]) != blob.size())
3349 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());
3350 lengths[i] = blob.size();
3355 if ((blob.size()) && (blob.back() != '\0'))
3357 process_entrypoint_warning("%s: String %u doesn't end in 0 terminator - appending terminator\n", VOGL_METHOD_NAME, i);
3359 blob.push_back('\0');
3362 VOGL_ASSERT(blob.size() &&
3363 (blob.back() == '\0') &&
3364 (blob.size() == (1 + vogl_strlen(reinterpret_cast<const char *>(blob.get_ptr())))));
3367 strings[i] = reinterpret_cast<const GLcharARB *>(blob.get_ptr());
3370 if (m_pCur_gl_packet->get_entrypoint_id() == VOGL_ENTRYPOINT_glShaderSource)
3372 GL_ENTRYPOINT(glShaderSource)(replay_object,
3374 trace_strings_glchar_ptr_array.get_ptr() ? (GLchar * const *)strings.get_ptr() : NULL,
3375 pTrace_lengths ? lengths.get_ptr() : NULL);
3379 GL_ENTRYPOINT(glShaderSourceARB)(replay_object,
3381 trace_strings_glchar_ptr_array.get_ptr() ? strings.get_ptr() : NULL,
3382 pTrace_lengths ? lengths.get_ptr() : NULL);
3387 //----------------------------------------------------------------------------------------------------------------------
3388 // vogl_gl_replayer::display_list_bind_callback
3389 // handle is in the trace namespace
3390 //----------------------------------------------------------------------------------------------------------------------
3391 void vogl_gl_replayer::display_list_bind_callback(vogl_namespace_t handle_namespace, GLenum target, GLuint handle, void *pOpaque)
3395 vogl_gl_replayer *pReplayer = static_cast<vogl_gl_replayer *>(pOpaque);
3397 if (handle_namespace == VOGL_NAMESPACE_TEXTURES)
3399 if ((handle) && (target != GL_NONE))
3401 // A conditional update because we can't really test to see if the bind inside the display list really succeeded.
3402 pReplayer->get_shared_state()->m_shadow_state.m_textures.conditional_update(handle, GL_NONE, target);
3407 // TODO - right now the display list whitelist doens't let anything else get bound.
3408 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);
3412 //----------------------------------------------------------------------------------------------------------------------
3413 // Helper macros - slightly simplifies hand-generating entrypoints with EXT/ARB/etc. variants
3414 //----------------------------------------------------------------------------------------------------------------------
3415 #define SWITCH_GL_ENTRYPOINT2(e0, e1, ...) \
3416 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3417 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3419 result = GL_ENTRYPOINT(e1)(__VA_ARGS__);
3421 #define SWITCH_GL_ENTRYPOINT3(e0, e1, e2, ...) \
3422 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3423 result = GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3424 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3425 result = GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3427 result = GL_ENTRYPOINT(e2)(__VA_ARGS__);
3429 #define SWITCH_GL_ENTRYPOINT2_VOID(e0, e1, ...) \
3430 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3431 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3433 GL_ENTRYPOINT(e1)(__VA_ARGS__);
3435 #define SWITCH_GL_ENTRYPOINT3_VOID(e0, e1, e2, ...) \
3436 if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e0)) \
3437 GL_ENTRYPOINT(e0)(__VA_ARGS__); \
3438 else if (entrypoint_id == VOGL_JOIN(VOGL_ENTRYPOINT_, e1)) \
3439 GL_ENTRYPOINT(e1)(__VA_ARGS__); \
3441 GL_ENTRYPOINT(e2)(__VA_ARGS__);
3443 //----------------------------------------------------------------------------------------------------------------------
3444 // vogl_replayer::process_gl_entrypoint_packet
3445 // This will be called during replaying, or when building display lists during state restoring.
3446 //----------------------------------------------------------------------------------------------------------------------
3447 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet(vogl_trace_packet& trace_packet)
3449 m_pCur_gl_packet = &trace_packet;
3451 status_t status = cStatusOK;
3453 if (m_pPending_snapshot)
3455 status = process_applying_pending_snapshot();
3456 if (status != cStatusOK)
3460 if (m_pending_make_current_packet.is_valid())
3462 status = process_pending_make_current();
3463 if (status != cStatusOK)
3467 const vogl_trace_gl_entrypoint_packet &entrypoint_packet = trace_packet.get_entrypoint_packet();
3469 m_last_parsed_call_counter = entrypoint_packet.m_call_counter;
3471 status = process_gl_entrypoint_packet_internal(trace_packet);
3473 if (status != cStatusResizeWindow)
3474 m_last_processed_call_counter = entrypoint_packet.m_call_counter;
3476 m_pCur_gl_packet = NULL;
3481 //----------------------------------------------------------------------------------------------------------------------
3482 // vogl_replayer::process_gl_entrypoint_packet_internal
3483 // This will be called during replaying, or when building display lists during state restoring.
3484 //----------------------------------------------------------------------------------------------------------------------
3485 vogl_gl_replayer::status_t vogl_gl_replayer::process_gl_entrypoint_packet_internal(vogl_trace_packet& trace_packet)
3489 m_at_frame_boundary = false;
3491 const vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = trace_packet.get_entrypoint_packet();
3492 const gl_entrypoint_id_t entrypoint_id = trace_packet.get_entrypoint_id();
3494 if (m_flags & cGLReplayerDebugMode)
3495 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
3497 if (m_flags & cGLReplayerDebugMode)
3498 dump_packet_as_func_call(trace_packet);
3500 if (m_flags & cGLReplayerDumpAllPackets)
3501 print_detailed_context(cDebugConsoleMessage);
3503 if (entrypoint_id == VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
3504 return process_internal_trace_command(gl_entrypoint_packet);
3506 status_t status = cStatusOK;
3508 if (gl_entrypoint_packet.m_context_handle != m_cur_trace_context)
3510 status = switch_contexts(gl_entrypoint_packet.m_context_handle);
3511 if (status != cStatusOK)
3515 bool processed_glx_packet = true;
3516 switch (entrypoint_id)
3518 case VOGL_ENTRYPOINT_glXDestroyContext:
3520 const Display *dpy = m_pWindow->get_display();
3522 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3523 GLXContext replay_context = remap_context(trace_context);
3525 if ((trace_context) && (!replay_context))
3527 process_entrypoint_error("%s: Failed remapping GL trace context 0x%" PRIx64 "\n", VOGL_METHOD_NAME, (uint64_t)trace_context);
3528 return cStatusHardFailure;
3531 if (trace_context == m_cur_trace_context)
3533 process_entrypoint_warning("%s: glXDestroyContext() called while trace context 0x%" PRIx64 " is still current, forcing it to not be current\n",
3534 VOGL_METHOD_NAME, (uint64_t)trace_context);
3536 m_cur_trace_context = 0;
3537 m_cur_replay_context = 0;
3538 m_pCur_context_state = NULL;
3541 GL_ENTRYPOINT(glXDestroyContext)(dpy, replay_context);
3543 destroy_context(trace_context);
3547 case VOGL_ENTRYPOINT_glXMakeCurrent:
3548 case VOGL_ENTRYPOINT_glXMakeContextCurrent:
3550 Bool trace_result = trace_packet.get_return_value<Bool>();
3552 vogl_trace_context_ptr_value trace_context = trace_packet.get_param_ptr_value((entrypoint_id == VOGL_ENTRYPOINT_glXMakeCurrent) ? 2 : 3);
3554 // pContext_state can be NULL!
3555 context_state *pContext_state = get_trace_context_state(trace_context);
3556 GLXContext replay_context = pContext_state ? pContext_state->m_replay_context : 0;
3558 if ((trace_context) && (!replay_context))
3560 process_entrypoint_error("%s, Failed remapping GL context\n", VOGL_METHOD_NAME);
3561 return cStatusHardFailure;
3564 int viewport_x = trace_packet.get_key_value_map().get_int(string_hash("viewport_x"));
3565 VOGL_NOTE_UNUSED(viewport_x);
3566 int viewport_y = trace_packet.get_key_value_map().get_int(string_hash("viewport_y"));
3567 VOGL_NOTE_UNUSED(viewport_y);
3568 int viewport_width = trace_packet.get_key_value_map().get_int(string_hash("viewport_width"));
3569 VOGL_NOTE_UNUSED(viewport_width);
3570 int viewport_height = trace_packet.get_key_value_map().get_int(string_hash("viewport_height"));
3571 VOGL_NOTE_UNUSED(viewport_height);
3572 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3573 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3575 // 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.
3576 if ((trace_context) && (trace_result))
3578 if ((win_width) && (win_height))
3580 if (!(m_flags & cGLReplayerLockWindowDimensions))
3582 if ((m_pWindow->get_width() != win_width) || (m_pWindow->get_height() != win_height))
3584 m_pending_make_current_packet = *m_pCur_gl_packet;
3586 status = trigger_pending_window_resize(win_width, win_height);
3588 vogl_printf("%s: Deferring glXMakeCurrent() until window resizes to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3594 if (status != cStatusResizeWindow)
3596 const Display *dpy = m_pWindow->get_display();
3597 GLXDrawable drawable = replay_context ? m_pWindow->get_xwindow() : (GLXDrawable)NULL;
3599 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
3604 process_entrypoint_error("%s: Failed making context current, but in the trace this call succeeded!\n", VOGL_METHOD_NAME);
3605 return cStatusHardFailure;
3609 process_entrypoint_warning("%s: Failed making context current, in the trace this call also failed\n", VOGL_METHOD_NAME);
3614 m_cur_trace_context = trace_context;
3615 m_cur_replay_context = replay_context;
3616 m_pCur_context_state = pContext_state;
3620 process_entrypoint_warning("%s: Context was successfuly made current, but this operation failed in the trace\n", VOGL_METHOD_NAME);
3624 vogl_printf("glXMakeCurrent(): Trace Viewport: [%u,%u,%u,%u], Window: [%u %u]\n",
3625 viewport_x, viewport_y,
3626 viewport_width, viewport_height,
3627 win_width, win_height);
3630 if (m_cur_replay_context)
3632 if (!handle_context_made_current())
3633 return cStatusHardFailure;
3640 case VOGL_ENTRYPOINT_glXQueryVersion:
3642 int major = 0, minor = 0;
3643 Bool status = GL_ENTRYPOINT(glXQueryVersion)(m_pWindow->get_display(), &major, &minor);
3644 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,
3645 *trace_packet.get_param_client_memory<int>(1),
3646 *trace_packet.get_param_client_memory<int>(2),
3647 trace_packet.get_return_value<Bool>());
3651 case VOGL_ENTRYPOINT_glXChooseFBConfig:
3656 case VOGL_ENTRYPOINT_glXGetFBConfigAttrib:
3661 case VOGL_ENTRYPOINT_glXGetVisualFromFBConfig:
3666 case VOGL_ENTRYPOINT_glXGetProcAddress:
3667 case VOGL_ENTRYPOINT_glXGetProcAddressARB:
3669 const GLubyte *procName = trace_packet.get_param_client_memory<GLubyte>(0);
3670 vogl_trace_ptr_value trace_func_ptr_value = trace_packet.get_return_ptr_value();
3672 void *pFunc = (void *)GL_ENTRYPOINT(glXGetProcAddress)(procName);
3674 if ((pFunc != NULL) != (trace_func_ptr_value != 0))
3676 process_entrypoint_warning("%s: glXGetProcAddress of function %s %s in the replay, but %s in the trace\n", VOGL_METHOD_NAME,
3677 (const char *)procName,
3678 (pFunc != NULL) ? "succeeded" : "failed",
3679 (trace_func_ptr_value != 0) ? "succeeded" : "failed");
3684 case VOGL_ENTRYPOINT_glXCreateNewContext:
3686 Display *dpy = m_pWindow->get_display();
3687 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3688 int render_type = trace_packet.get_param_value<GLint>(2);
3690 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(3);
3691 GLXContext replay_share_context = remap_context(trace_share_context);
3693 if ((trace_share_context) && (!replay_share_context))
3695 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3698 Bool direct = trace_packet.get_param_value<Bool>(4);
3699 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3701 if (m_flags & cGLReplayerForceDebugContexts)
3703 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);
3705 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3706 if (status != cStatusOK)
3711 GLXContext replay_context = GL_ENTRYPOINT(glXCreateNewContext)(dpy, fb_config, render_type, replay_share_context, direct);
3713 if (!replay_context)
3717 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3718 return cStatusHardFailure;
3722 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3730 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateNewContext, NULL, 0);
3731 VOGL_NOTE_UNUSED(pContext_state);
3735 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3742 case VOGL_ENTRYPOINT_glXCreateContext:
3744 Display *dpy = m_pWindow->get_display();
3746 vogl_trace_context_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3747 GLXContext replay_share_context = remap_context(trace_share_context);
3749 if ((trace_share_context) && (!replay_share_context))
3751 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3754 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3755 Bool direct = trace_packet.get_param_value<Bool>(3);
3756 vogl_trace_context_ptr_value trace_context = trace_packet.get_return_ptr_value();
3758 if (m_flags & cGLReplayerForceDebugContexts)
3760 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, NULL, 0, false);
3761 if (status != cStatusOK)
3766 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(dpy, fb_config);
3768 GLXContext replay_context = GL_ENTRYPOINT(glXCreateContext)(dpy, pVisual_info, replay_share_context, direct);
3770 if (!replay_context)
3774 process_entrypoint_error("%s: Failed creating new GL context!\n", VOGL_METHOD_NAME);
3775 return cStatusHardFailure;
3779 process_entrypoint_warning("%s: Successfully created a new GL context where the traced app failed!\n", VOGL_METHOD_NAME);
3787 context_state *pContext_state = define_new_context(trace_context, replay_context, trace_share_context, direct, VOGL_ENTRYPOINT_glXCreateContext, NULL, 0);
3788 VOGL_NOTE_UNUSED(pContext_state);
3792 GL_ENTRYPOINT(glXDestroyContext)(m_pWindow->get_display(), replay_context);
3799 case VOGL_ENTRYPOINT_glXCreateContextAttribsARB:
3801 Display *dpy = m_pWindow->get_display();
3802 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
3804 vogl_trace_ptr_value trace_share_context = trace_packet.get_param_ptr_value(2);
3805 GLXContext replay_share_context = remap_context(trace_share_context);
3807 if ((trace_share_context) && (!replay_share_context))
3809 process_entrypoint_warning("%s: Failed remapping trace sharelist context 0x%" PRIx64 "!\n", VOGL_METHOD_NAME, cast_val_to_uint64(trace_share_context));
3812 Bool direct = trace_packet.get_param_value<Bool>(3);
3813 const int *pTrace_attrib_list = static_cast<const int *>(trace_packet.get_param_client_memory_ptr(4));
3814 const uint trace_attrib_list_size = trace_packet.get_param_client_memory_data_size(4) / sizeof(int);
3816 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3818 status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct, pTrace_attrib_list, trace_attrib_list_size, true);
3819 if (status != cStatusOK)
3824 case VOGL_ENTRYPOINT_glXSwapBuffers:
3826 check_program_binding_shadow();
3828 if (m_flags & cGLReplayerLowLevelDebugMode)
3830 if (!validate_program_and_shader_handle_tables())
3831 vogl_warning_printf("%s: Failed validating program/shaders against handle mapping tables\n", VOGL_METHOD_NAME);
3832 if (!validate_textures())
3833 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
3836 const Display *dpy = m_pWindow->get_display();
3837 GLXDrawable drawable = m_pWindow->get_xwindow();
3839 if ((m_flags & cGLReplayerHashBackbuffer) || (m_flags & cGLReplayerDumpScreenshots) || (m_flags & cGLReplayerDumpBackbufferHashes))
3841 snapshot_backbuffer();
3844 if (m_dump_frontbuffer_filename.has_content())
3846 dump_frontbuffer_to_file(m_dump_frontbuffer_filename);
3847 m_dump_frontbuffer_filename.clear();
3850 GL_ENTRYPOINT(glXSwapBuffers)(dpy, drawable);
3852 if (m_swap_sleep_time)
3853 vogl_sleep(m_swap_sleep_time);
3855 status = cStatusNextFrame;
3857 m_at_frame_boundary = true;
3859 if (m_flags & cGLReplayerDebugMode)
3861 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);
3867 m_frame_draw_counter = 0;
3869 int win_width = trace_packet.get_key_value_map().get_int(string_hash("win_width"));
3870 int win_height = trace_packet.get_key_value_map().get_int(string_hash("win_height"));
3871 if ((win_width) && (win_height))
3873 if (!(m_flags & cGLReplayerLockWindowDimensions))
3875 if ((win_width != m_pWindow->get_width()) || (win_height != m_pWindow->get_height()))
3877 // TODO: This resize might need to be deferred until the window system actually resizes the window.
3878 //m_pWindow->resize(win_width, win_height);
3879 trigger_pending_window_resize(win_width, win_height);
3881 vogl_printf("%s: Resizing window after swap to %ux%u\n", VOGL_METHOD_NAME, win_width, win_height);
3888 case VOGL_ENTRYPOINT_glXWaitX:
3890 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitX;
3892 VOGL_REPLAY_CALL_GL_HELPER_glXWaitX;
3896 case VOGL_ENTRYPOINT_glXWaitGL:
3898 VOGL_REPLAY_LOAD_PARAMS_HELPER_glXWaitGL;
3900 VOGL_REPLAY_CALL_GL_HELPER_glXWaitGL;
3904 case VOGL_ENTRYPOINT_glXIsDirect:
3906 const Display *dpy = m_pWindow->get_display();
3908 vogl_trace_ptr_value trace_context = trace_packet.get_param_ptr_value(1);
3909 GLXContext replay_context = remap_context(trace_context);
3911 Bool replay_is_direct = GL_ENTRYPOINT(glXIsDirect)(dpy, replay_context);
3912 Bool trace_is_direct = trace_packet.get_return_value<Bool>();
3914 if (replay_is_direct != trace_is_direct)
3916 process_entrypoint_warning("%s: glXIsDirect() returned different results while replaying (%u) vs tracing (%u)!\n", VOGL_METHOD_NAME, replay_is_direct, trace_is_direct);
3921 case VOGL_ENTRYPOINT_glXGetCurrentContext:
3923 GLXContext replay_context = GL_ENTRYPOINT(glXGetCurrentContext)();
3924 vogl_trace_ptr_value trace_context = trace_packet.get_return_ptr_value();
3926 if ((replay_context != 0) != (trace_context != 0))
3928 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);
3933 case VOGL_ENTRYPOINT_glXCreateWindow:
3934 case VOGL_ENTRYPOINT_glXDestroyWindow:
3935 case VOGL_ENTRYPOINT_glXChooseVisual:
3936 case VOGL_ENTRYPOINT_glXGetCurrentDisplay:
3937 case VOGL_ENTRYPOINT_glXQueryDrawable:
3938 case VOGL_ENTRYPOINT_glXQueryExtension:
3939 case VOGL_ENTRYPOINT_glXQueryExtensionsString:
3940 case VOGL_ENTRYPOINT_glXSwapIntervalEXT:
3941 case VOGL_ENTRYPOINT_glXSwapIntervalSGI:
3942 case VOGL_ENTRYPOINT_glXGetCurrentDrawable:
3943 case VOGL_ENTRYPOINT_glXGetCurrentReadDrawable:
3944 case VOGL_ENTRYPOINT_glXQueryContext:
3945 case VOGL_ENTRYPOINT_glXGetClientString:
3946 case VOGL_ENTRYPOINT_glXGetConfig:
3947 case VOGL_ENTRYPOINT_glXGetFBConfigs:
3954 processed_glx_packet = false;
3959 if (processed_glx_packet)
3961 // TODO: Check for GLX errors?
3965 if (!m_cur_replay_context)
3967 process_entrypoint_error("%s: Trace contains a GL call with no current context! Skipping call.\n", VOGL_METHOD_NAME);
3968 return cStatusSoftFailure;
3971 VOGL_ASSERT(m_pCur_context_state);
3972 m_pCur_context_state->m_last_call_counter = m_last_parsed_call_counter;
3974 #ifdef VOGL_BUILD_DEBUG
3975 VOGL_ASSERT(get_trace_context_state(m_cur_trace_context) == m_pCur_context_state);
3978 // Add call to current display list
3979 if ((get_context_state()->is_composing_display_list()) && (g_vogl_entrypoint_descs[entrypoint_id].m_is_listable))
3981 if (!vogl_display_list_state::is_call_listable(entrypoint_id, trace_packet))
3983 if (!g_vogl_entrypoint_descs[entrypoint_id].m_whitelisted_for_displaylists)
3984 process_entrypoint_error("%s: Failed serializing trace packet into display list shadow! Call is not listable.\n", VOGL_FUNCTION_NAME);
3986 process_entrypoint_warning("%s: Failed serializing trace packet into display list shadow! Call with these parameters is not listable.\n", VOGL_FUNCTION_NAME);
3990 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))
3992 process_entrypoint_warning("%s: Failed adding current packet to display list shadow!\n", VOGL_METHOD_NAME);
3997 switch (entrypoint_id)
3999 // ----- Create simple auto-generated replay funcs - voglgen creates this inc file from the funcs in gl_glx_simple_replay_funcs.txt
4000 // These simple GL entrypoints only take value params that don't require handle remapping, or simple pointers to client memory
4001 // (typically pointers to fixed size buffers, or params directly controlling the size of buffers).
4002 #define VOGL_SIMPLE_REPLAY_FUNC_BEGIN(name, num_params) \
4003 case VOGL_ENTRYPOINT_##name: \
4004 { GL_ENTRYPOINT(name)(
4005 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(type, index) trace_packet.get_param_value<type>(index)
4006 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR ,
4007 #define VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(type, index) trace_packet.get_param_client_memory<type>(index)
4008 #define VOGL_SIMPLE_REPLAY_FUNC_END(name) ); \
4011 #include "gl_glx_simple_replay_funcs.inc"
4012 #undef VOGL_SIMPLE_REPLAY_FUNC_BEGIN
4013 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE
4014 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR
4015 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY
4016 #undef VOGL_SIMPLE_REPLAY_FUNC_PARAM_END
4018 case VOGL_ENTRYPOINT_glXUseXFont:
4020 const key_value_map &key_value_map = trace_packet.get_key_value_map();
4022 const dynamic_string *pFont_name = key_value_map.get_string_ptr("font_name");
4023 if ((!pFont_name) || (pFont_name->is_empty()))
4025 process_entrypoint_warning("%s: Couldn't find font_name key, or key was empty - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME);
4029 XFontStruct *pFont = XLoadQueryFont(m_pWindow->get_display(), pFont_name->get_ptr());
4032 process_entrypoint_warning("%s: Couldn't load X font %s - unable to call glXUseXFont()!\n", VOGL_METHOD_NAME, pFont_name->get_ptr());
4036 GLint first = trace_packet.get_param_value<int>(1);
4037 GLint count = trace_packet.get_param_value<int>(2);
4038 int trace_list_base = trace_packet.get_param_value<int>(3);
4039 GLuint replay_list_base = map_handle(get_shared_state()->m_lists, trace_list_base);
4041 GL_ENTRYPOINT(glXUseXFont)(pFont->fid, first, count, replay_list_base);
4043 XFreeFont(m_pWindow->get_display(), pFont);
4045 if (get_context_state()->is_composing_display_list())
4047 process_entrypoint_warning("%s: glXUseXFont() called while composing a display list!\n", VOGL_METHOD_NAME);
4051 if (!get_shared_state()->m_shadow_state.m_display_lists.glx_font(pFont_name->get_ptr(), first, count, trace_list_base))
4053 process_entrypoint_warning("%s: Failed updating display list shadow\n", VOGL_METHOD_NAME);
4061 case VOGL_ENTRYPOINT_glBlitFramebufferEXT:
4063 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebufferEXT;
4065 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebufferEXT;
4067 if ((status = post_draw_call()) != cStatusOK)
4072 case VOGL_ENTRYPOINT_glBlitFramebuffer:
4074 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBlitFramebuffer;
4076 VOGL_REPLAY_CALL_GL_HELPER_glBlitFramebuffer;
4078 if ((status = post_draw_call()) != cStatusOK)
4083 case VOGL_ENTRYPOINT_glBegin:
4085 if (m_pCur_context_state->m_inside_gl_begin)
4087 process_entrypoint_warning("%s: Got a glBegin while already inside a glBegin\n", VOGL_METHOD_NAME);
4089 m_pCur_context_state->m_inside_gl_begin = true;
4091 g_vogl_actual_gl_entrypoints.m_glBegin(trace_packet.get_param_value<GLenum>(0));
4095 case VOGL_ENTRYPOINT_glEnd:
4097 if (!m_pCur_context_state->m_inside_gl_begin)
4099 process_entrypoint_warning("%s: Got glEnd without a matching glBegin\n", VOGL_METHOD_NAME);
4101 m_pCur_context_state->m_inside_gl_begin = false;
4103 g_vogl_actual_gl_entrypoints.m_glEnd();
4105 if ((status = post_draw_call()) != cStatusOK)
4110 case VOGL_ENTRYPOINT_glGetError:
4112 // TODO: Compare trace error vs. replay error
4116 case VOGL_ENTRYPOINT_glGetStringi:
4118 if (!benchmark_mode())
4120 const GLubyte *pStr = GL_ENTRYPOINT(glGetStringi)(
4121 trace_packet.get_param_value<GLenum>(0),
4122 trace_packet.get_param_value<GLuint>(1));
4123 VOGL_NOTE_UNUSED(pStr);
4125 // TODO: Compare vs. trace's?
4130 case VOGL_ENTRYPOINT_glGetString:
4132 if (!benchmark_mode())
4134 const GLubyte *pStr = GL_ENTRYPOINT(glGetString)(
4135 trace_packet.get_param_value<GLenum>(0));
4136 VOGL_NOTE_UNUSED(pStr);
4138 // TODO: Compare vs. trace's?
4143 case VOGL_ENTRYPOINT_glGenFramebuffers:
4144 case VOGL_ENTRYPOINT_glGenFramebuffersEXT:
4146 if (!gen_handles(get_context_state()->m_framebuffers,
4147 trace_packet.get_param_value<GLsizei>(0),
4148 static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1)),
4149 (entrypoint_id == VOGL_ENTRYPOINT_glGenFramebuffers) ? GL_ENTRYPOINT(glGenFramebuffers) : GL_ENTRYPOINT(glGenFramebuffersEXT), NULL))
4150 return cStatusHardFailure;
4154 case VOGL_ENTRYPOINT_glBindFramebuffer:
4155 case VOGL_ENTRYPOINT_glBindFramebufferEXT:
4157 GLenum target = trace_packet.get_param_value<GLenum>(0);
4158 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
4160 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
4162 SWITCH_GL_ENTRYPOINT2_VOID(glBindFramebuffer, glBindFramebufferEXT, target, replay_handle);
4166 case VOGL_ENTRYPOINT_glGetRenderbufferParameterivEXT:
4167 case VOGL_ENTRYPOINT_glGetRenderbufferParameteriv:
4169 if (!benchmark_mode())
4171 GLenum target = trace_packet.get_param_value<GLenum>(0);
4172 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4173 GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(2);
4174 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
4175 uint trace_params_count = trace_params_size / sizeof(GLint);
4177 int n = g_gl_enums.get_pname_count(pname);
4180 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4181 return cStatusSoftFailure;
4183 else if (n < static_cast<int>(trace_params_count))
4185 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);
4186 return cStatusSoftFailure;
4190 vogl::growable_array<GLint, 16> params(n + 1);
4191 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4193 SWITCH_GL_ENTRYPOINT2_VOID(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT, target, pname, params.get_ptr());
4195 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4197 if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
4199 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));
4206 case VOGL_ENTRYPOINT_glCheckFramebufferStatus:
4207 case VOGL_ENTRYPOINT_glCheckFramebufferStatusEXT:
4210 SWITCH_GL_ENTRYPOINT2(glCheckFramebufferStatus, glCheckFramebufferStatusEXT, trace_packet.get_param_value<GLenum>(0));
4212 GLenum trace_status = trace_packet.get_return_value<GLenum>();
4213 if (result != trace_status)
4215 process_entrypoint_warning("%s: glCheckFramebufferStatus returned status 0x%08X during trace, but status 0x%08X during replay\n", VOGL_METHOD_NAME, trace_status, result);
4219 case VOGL_ENTRYPOINT_glDeleteFramebuffers:
4221 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));
4224 case VOGL_ENTRYPOINT_glDeleteFramebuffersEXT:
4226 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));
4229 case VOGL_ENTRYPOINT_glFramebufferTexture:
4231 GLenum target = trace_packet.get_param_value<GLenum>(0);
4232 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4233 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4234 GLuint replay_texture = trace_texture;
4235 GLint level = trace_packet.get_param_value<GLint>(3);
4237 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4240 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);
4243 GL_ENTRYPOINT(glFramebufferTexture)(target, attachment, replay_texture, level);
4247 case VOGL_ENTRYPOINT_glFramebufferTextureLayer:
4248 case VOGL_ENTRYPOINT_glFramebufferTextureLayerEXT:
4250 GLenum target = trace_packet.get_param_value<GLenum>(0);
4251 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4252 GLuint trace_texture = trace_packet.get_param_value<GLuint>(2);
4253 GLuint replay_texture = trace_texture;
4254 GLint level = trace_packet.get_param_value<GLint>(3);
4255 GLint layer = trace_packet.get_param_value<GLint>(4);
4257 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4260 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);
4263 SWITCH_GL_ENTRYPOINT2_VOID(glFramebufferTextureLayer, glFramebufferTextureLayerEXT, target, attachment, replay_texture, level, layer);
4267 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4268 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4269 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4270 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4271 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4272 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4274 GLenum target = trace_packet.get_param_value<GLenum>(0);
4275 GLenum attachment = trace_packet.get_param_value<GLenum>(1);
4276 GLenum textarget = trace_packet.get_param_value<GLenum>(2);
4277 GLuint trace_texture = trace_packet.get_param_value<GLuint>(3);
4278 GLuint replay_texture = trace_texture;
4279 GLint level = trace_packet.get_param_value<GLint>(4);
4281 if (!get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(trace_texture, replay_texture))
4284 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);
4287 switch (entrypoint_id)
4289 case VOGL_ENTRYPOINT_glFramebufferTexture1DEXT:
4290 GL_ENTRYPOINT(glFramebufferTexture1DEXT)(target, attachment, textarget, replay_texture, level);
4292 case VOGL_ENTRYPOINT_glFramebufferTexture1D:
4293 GL_ENTRYPOINT(glFramebufferTexture1D)(target, attachment, textarget, replay_texture, level);
4295 case VOGL_ENTRYPOINT_glFramebufferTexture2DEXT:
4296 GL_ENTRYPOINT(glFramebufferTexture2DEXT)(target, attachment, textarget, replay_texture, level);
4298 case VOGL_ENTRYPOINT_glFramebufferTexture2D:
4299 GL_ENTRYPOINT(glFramebufferTexture2D)(target, attachment, textarget, replay_texture, level);
4301 case VOGL_ENTRYPOINT_glFramebufferTexture3DEXT:
4302 GL_ENTRYPOINT(glFramebufferTexture3DEXT)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4304 case VOGL_ENTRYPOINT_glFramebufferTexture3D:
4305 GL_ENTRYPOINT(glFramebufferTexture3D)(target, attachment, textarget, replay_texture, level, trace_packet.get_param_value<GLint>(5));
4313 case VOGL_ENTRYPOINT_glGenTextures:
4315 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))
4316 return cStatusHardFailure;
4319 case VOGL_ENTRYPOINT_glGenTexturesEXT:
4321 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))
4322 return cStatusHardFailure;
4325 case VOGL_ENTRYPOINT_glDeleteTextures:
4327 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));
4330 case VOGL_ENTRYPOINT_glDeleteTexturesEXT:
4332 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));
4335 case VOGL_ENTRYPOINT_glBindMultiTextureEXT:
4337 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindMultiTextureEXT;
4339 GLuint trace_texture = texture;
4340 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4342 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4345 VOGL_REPLAY_CALL_GL_HELPER_glBindMultiTextureEXT;
4347 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4349 if (!check_gl_error())
4350 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4355 case VOGL_ENTRYPOINT_glBindTexture:
4356 case VOGL_ENTRYPOINT_glBindTextureEXT:
4358 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindTexture;
4360 GLuint trace_texture = texture;
4361 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_texture, texture);
4363 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4366 SWITCH_GL_ENTRYPOINT2_VOID(glBindTexture, glBindTextureEXT, target, texture);
4368 if ((texture) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4370 if (!check_gl_error())
4371 get_shared_state()->m_shadow_state.m_textures.update(trace_texture, texture, target);
4376 case VOGL_ENTRYPOINT_glBindSampler:
4378 GLuint replay_handle = map_handle(get_shared_state()->m_sampler_objects, trace_packet.get_param_value<GLuint>(1));
4379 GL_ENTRYPOINT(glBindSampler)(trace_packet.get_param_value<GLuint>(0), replay_handle);
4382 case VOGL_ENTRYPOINT_glDeleteSamplers:
4384 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));
4387 case VOGL_ENTRYPOINT_glGenSamplers:
4389 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))
4390 return cStatusHardFailure;
4394 case VOGL_ENTRYPOINT_glSamplerParameterf:
4396 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterf;
4397 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4398 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterf;
4401 case VOGL_ENTRYPOINT_glSamplerParameteri:
4403 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteri;
4404 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4405 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteri;
4408 case VOGL_ENTRYPOINT_glSamplerParameterfv:
4410 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterfv;
4411 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4412 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterfv;
4415 case VOGL_ENTRYPOINT_glSamplerParameteriv:
4417 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameteriv;
4418 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4419 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameteriv;
4422 case VOGL_ENTRYPOINT_glSamplerParameterIiv:
4424 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIiv;
4425 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4426 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIiv;
4429 case VOGL_ENTRYPOINT_glSamplerParameterIuiv:
4431 VOGL_REPLAY_LOAD_PARAMS_HELPER_glSamplerParameterIuiv;
4432 sampler = map_handle(get_shared_state()->m_sampler_objects, sampler);
4433 VOGL_REPLAY_CALL_GL_HELPER_glSamplerParameterIuiv;
4436 case VOGL_ENTRYPOINT_glGenBuffers:
4437 case VOGL_ENTRYPOINT_glGenBuffersARB:
4439 uint n = trace_packet.get_param_value<GLsizei>(0);
4440 const GLuint *pTrace_handles = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4442 if (entrypoint_id == VOGL_ENTRYPOINT_glGenBuffers)
4444 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffers), NULL))
4445 return cStatusHardFailure;
4449 if (!gen_handles(get_shared_state()->m_buffers, n, pTrace_handles, GL_ENTRYPOINT(glGenBuffersARB), NULL))
4450 return cStatusHardFailure;
4455 for (uint i = 0; i < n; i++)
4457 if (pTrace_handles[i])
4458 get_shared_state()->m_buffer_targets.insert(pTrace_handles[i], GL_NONE);
4464 case VOGL_ENTRYPOINT_glDeleteBuffers:
4465 case VOGL_ENTRYPOINT_glDeleteBuffersARB:
4467 GLsizei trace_n = trace_packet.get_param_value<GLsizei>(0);
4468 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4469 uint trace_ids_count = trace_packet.get_param_client_memory_data_size(1);
4471 if ((pTrace_ids) && (static_cast<GLsizei>(trace_ids_count) < trace_n))
4473 process_entrypoint_warning("%s: trace_ids trace array is too small\n", VOGL_METHOD_NAME);
4474 return cStatusHardFailure;
4477 for (GLsizei iter = 0; iter < trace_n; iter++)
4479 GLuint trace_id = pTrace_ids[iter];
4483 if (!get_shared_state()->m_buffer_targets.erase(trace_id))
4485 process_entrypoint_warning("%s: Couldn't find trace buffer id %u in buffer target map!\n", VOGL_METHOD_NAME, trace_id);
4488 gl_handle_hash_map::const_iterator it = get_shared_state()->m_buffers.find(trace_id);
4489 if (it == get_shared_state()->m_buffers.end())
4491 process_entrypoint_warning("%s: Couldn't map trace buffer id %u to GL buffer id\n", VOGL_METHOD_NAME, trace_id);
4495 GLuint replay_id = it->second;
4497 for (uint i = 0; i < get_shared_state()->m_mapped_buffers.size(); i++)
4499 if (get_shared_state()->m_mapped_buffers[i].m_buffer == replay_id)
4501 process_entrypoint_warning("%s: glDeleteBuffers() called on mapped trace buffer %u GL buffer %u\n", VOGL_METHOD_NAME, trace_id, replay_id);
4503 get_shared_state()->m_mapped_buffers.erase_unordered(i);
4509 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteBuffers)
4510 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffers));
4512 delete_handles(get_shared_state()->m_buffers, trace_n, pTrace_ids, GL_ENTRYPOINT(glDeleteBuffersARB));
4516 case VOGL_ENTRYPOINT_glGenProgramsARB:
4518 // arb program objects
4519 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGenProgramsARB;
4521 if (!gen_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glGenProgramsARB), NULL))
4522 return cStatusHardFailure;
4524 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4525 if (pTrace_programs[i])
4526 get_shared_state()->m_arb_program_targets.insert(pTrace_programs[i], GL_NONE);
4530 case VOGL_ENTRYPOINT_glDeleteProgramsARB:
4532 // arb program objects
4533 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDeleteProgramsARB;
4535 for (GLsizei i = 0; (pTrace_programs) && (i < n); i++)
4536 get_shared_state()->m_arb_program_targets.erase(pTrace_programs[i]);
4538 delete_handles(get_shared_state()->m_arb_programs, n, pTrace_programs, GL_ENTRYPOINT(glDeleteProgramsARB));
4541 case VOGL_ENTRYPOINT_glBindProgramARB:
4543 // arb program objects
4544 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindProgramARB;
4546 GLuint trace_program = program;
4547 gl_handle_hash_map::const_iterator it;
4550 it = get_shared_state()->m_arb_programs.find(program);
4551 if (it != get_shared_state()->m_arb_programs.end())
4552 program = it->second;
4554 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);
4559 VOGL_REPLAY_CALL_GL_HELPER_glBindProgramARB;
4561 if (!check_gl_error() && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
4565 if (it == get_shared_state()->m_arb_programs.end())
4566 get_shared_state()->m_arb_programs.insert(trace_program, program);
4568 get_shared_state()->m_arb_program_targets[trace_program] = target;
4573 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));
4574 return cStatusGLError;
4579 case VOGL_ENTRYPOINT_glIsProgramARB:
4581 if (!benchmark_mode())
4583 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIsProgramARB;
4585 GLuint trace_program = program;
4586 program = map_handle(get_shared_state()->m_arb_programs, program);
4588 GLboolean replay_result = VOGL_REPLAY_CALL_GL_HELPER_glIsProgramARB;
4589 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4591 if (trace_result != replay_result)
4592 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);
4597 case VOGL_ENTRYPOINT_glGenQueries:
4598 case VOGL_ENTRYPOINT_glGenQueriesARB:
4600 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4601 vogl::growable_array<GLuint, 16> replay_handles(n);
4603 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()))
4604 return cStatusHardFailure;
4606 for (GLsizei i = 0; i < n; i++)
4607 get_shared_state()->m_query_targets[replay_handles[i]] = GL_NONE;
4611 case VOGL_ENTRYPOINT_glDeleteQueries:
4612 case VOGL_ENTRYPOINT_glDeleteQueriesARB:
4614 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
4615 const GLuint *pTrace_ids = static_cast<const GLuint *>(trace_packet.get_param_client_memory_ptr(1));
4619 for (GLsizei i = 0; i < n; i++)
4621 GLuint trace_id = pTrace_ids[i];
4624 gl_handle_hash_map::const_iterator it(get_shared_state()->m_queries.find(trace_id));
4625 if (it != get_shared_state()->m_queries.end())
4626 get_shared_state()->m_query_targets.erase(it->second);
4630 if (entrypoint_id == VOGL_ENTRYPOINT_glDeleteQueries)
4631 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));
4633 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));
4637 case VOGL_ENTRYPOINT_glGenRenderbuffersEXT:
4639 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))
4640 return cStatusHardFailure;
4643 case VOGL_ENTRYPOINT_glGenRenderbuffers:
4645 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))
4646 return cStatusHardFailure;
4649 case VOGL_ENTRYPOINT_glDeleteRenderbuffersEXT:
4651 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));
4654 case VOGL_ENTRYPOINT_glDeleteRenderbuffers:
4656 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));
4659 case VOGL_ENTRYPOINT_glIsRenderbuffer:
4661 if (!benchmark_mode())
4663 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbuffer)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4664 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4665 if (replay_result != trace_result)
4667 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);
4672 case VOGL_ENTRYPOINT_glIsRenderbufferEXT:
4674 if (!benchmark_mode())
4676 GLboolean replay_result = GL_ENTRYPOINT(glIsRenderbufferEXT)(map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(0)));
4677 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
4678 if (replay_result != trace_result)
4680 process_entrypoint_warning("%s: Replay's returned GLboolean data differed from trace's (got %i, expected %i)\n", VOGL_METHOD_NAME, replay_result, replay_result);
4685 case VOGL_ENTRYPOINT_glBindRenderbufferEXT:
4687 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)));
4690 case VOGL_ENTRYPOINT_glBindRenderbuffer:
4692 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)));
4695 case VOGL_ENTRYPOINT_glFramebufferRenderbufferEXT:
4697 GL_ENTRYPOINT(glFramebufferRenderbufferEXT)(
4698 trace_packet.get_param_value<GLenum>(0),
4699 trace_packet.get_param_value<GLenum>(1),
4700 trace_packet.get_param_value<GLenum>(2),
4701 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4704 case VOGL_ENTRYPOINT_glFramebufferRenderbuffer:
4706 GL_ENTRYPOINT(glFramebufferRenderbuffer)(
4707 trace_packet.get_param_value<GLenum>(0),
4708 trace_packet.get_param_value<GLenum>(1),
4709 trace_packet.get_param_value<GLenum>(2),
4710 map_handle(get_shared_state()->m_shadow_state.m_rbos, trace_packet.get_param_value<GLuint>(3)));
4713 case VOGL_ENTRYPOINT_glUseProgramObjectARB:
4714 case VOGL_ENTRYPOINT_glUseProgram:
4716 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4717 handle_use_program(trace_handle, entrypoint_id);
4720 case VOGL_ENTRYPOINT_glProgramParameteri:
4721 case VOGL_ENTRYPOINT_glProgramParameteriARB:
4722 case VOGL_ENTRYPOINT_glProgramParameteriEXT:
4724 VOGL_REPLAY_LOAD_PARAMS_HELPER_glProgramParameteri;
4726 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4728 if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriARB)
4729 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriARB;
4730 else if (entrypoint_id == VOGL_ENTRYPOINT_glProgramParameteriEXT)
4731 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteriEXT;
4733 VOGL_REPLAY_CALL_GL_HELPER_glProgramParameteri;
4737 case VOGL_ENTRYPOINT_glBindFragDataLocation:
4738 case VOGL_ENTRYPOINT_glBindFragDataLocationEXT:
4740 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocation;
4742 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4744 if (entrypoint_id == VOGL_ENTRYPOINT_glBindFragDataLocation)
4745 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocation;
4747 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationEXT;
4751 case VOGL_ENTRYPOINT_glBindFragDataLocationIndexed:
4753 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindFragDataLocationIndexed;
4755 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4757 VOGL_REPLAY_CALL_GL_HELPER_glBindFragDataLocationIndexed;
4761 case VOGL_ENTRYPOINT_glValidateProgramARB:
4763 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgramARB;
4765 programObj = map_handle(get_shared_state()->m_shadow_state.m_objs, programObj);
4767 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgramARB;
4771 case VOGL_ENTRYPOINT_glValidateProgram:
4773 VOGL_REPLAY_LOAD_PARAMS_HELPER_glValidateProgram;
4775 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
4777 VOGL_REPLAY_CALL_GL_HELPER_glValidateProgram;
4781 case VOGL_ENTRYPOINT_glCreateProgram:
4782 case VOGL_ENTRYPOINT_glCreateProgramObjectARB:
4784 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4787 GLuint replay_handle;
4789 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateProgram)
4790 replay_handle = GL_ENTRYPOINT(glCreateProgram)();
4792 replay_handle = GL_ENTRYPOINT(glCreateProgramObjectARB)();
4794 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsProgram)(replay_handle) != 0));
4796 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_PROGRAM_OBJECT))
4797 return cStatusHardFailure;
4801 case VOGL_ENTRYPOINT_glDeleteProgram:
4803 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
4804 handle_delete_program(trace_handle);
4808 case VOGL_ENTRYPOINT_glDeleteObjectARB:
4810 GLuint trace_handle = trace_packet.get_param_value<GLenum>(0);
4811 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle);
4813 if (target == VOGL_SHADER_OBJECT)
4814 handle_delete_shader(trace_handle);
4815 else if (target == VOGL_PROGRAM_OBJECT)
4816 handle_delete_program(trace_handle);
4819 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
4821 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);
4822 return cStatusSoftFailure;
4827 case VOGL_ENTRYPOINT_glDeleteShader:
4829 GLuint trace_shader = trace_packet.get_param_value<GLuint>(0);
4830 handle_delete_shader(trace_shader);
4834 case VOGL_ENTRYPOINT_glCreateShader:
4835 case VOGL_ENTRYPOINT_glCreateShaderObjectARB:
4837 GLuint trace_handle = trace_packet.get_return_value<GLuint>();
4840 GLuint replay_handle;
4842 if (entrypoint_id == VOGL_ENTRYPOINT_glCreateShader)
4843 replay_handle = GL_ENTRYPOINT(glCreateShader)(trace_packet.get_param_value<GLenum>(0));
4845 replay_handle = GL_ENTRYPOINT(glCreateShaderObjectARB)(trace_packet.get_param_value<GLenum>(0));
4847 VOGL_ASSERT(!replay_handle || (GL_ENTRYPOINT(glIsShader)(replay_handle) != 0));
4849 if (!gen_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle, replay_handle, VOGL_SHADER_OBJECT))
4850 return cStatusHardFailure;
4854 case VOGL_ENTRYPOINT_glAttachShader:
4856 GL_ENTRYPOINT(glAttachShader)(
4857 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4858 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(1)));
4861 case VOGL_ENTRYPOINT_glAttachObjectARB:
4863 GL_ENTRYPOINT(glAttachObjectARB)(
4864 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4865 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(1)));
4868 case VOGL_ENTRYPOINT_glDetachShader:
4870 handle_detach_shader(entrypoint_id);
4874 case VOGL_ENTRYPOINT_glDetachObjectARB:
4876 GLhandleARB trace_object_handle = trace_packet.get_param_value<GLhandleARB>(1);
4878 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target(trace_object_handle);
4880 if (target == VOGL_SHADER_OBJECT)
4881 handle_detach_shader(entrypoint_id);
4884 GLuint replay_object_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object_handle);
4885 GL_ENTRYPOINT(glDetachObjectARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)), replay_object_handle);
4890 case VOGL_ENTRYPOINT_glBindAttribLocation:
4892 GL_ENTRYPOINT(glBindAttribLocation)(
4893 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)),
4894 trace_packet.get_param_value<GLuint>(1),
4895 trace_packet.get_param_client_memory<GLchar>(2));
4898 case VOGL_ENTRYPOINT_glBindAttribLocationARB:
4900 GL_ENTRYPOINT(glBindAttribLocationARB)(
4901 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4902 trace_packet.get_param_value<GLuint>(1),
4903 trace_packet.get_param_client_memory<GLcharARB>(2));
4906 case VOGL_ENTRYPOINT_glGetObjectParameterivARB:
4908 if (!benchmark_mode())
4910 GLenum pname = trace_packet.get_param_value<GLenum>(1);
4911 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
4913 int n = g_gl_enums.get_pname_count(pname);
4916 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
4917 return cStatusSoftFailure;
4921 vogl::growable_array<GLint, 16> params(n + 1);
4922 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4924 GL_ENTRYPOINT(glGetObjectParameterivARB)(
4925 map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)),
4929 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4931 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
4933 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));
4939 case VOGL_ENTRYPOINT_glGetBufferParameteriv:
4941 if (!benchmark_mode())
4943 GLenum target = trace_packet.get_param_value<GLenum>(0);
4944 GLenum value = trace_packet.get_param_value<GLenum>(1);
4945 const GLint *pTrace_data = trace_packet.get_param_client_memory<GLint>(2);
4947 int n = g_gl_enums.get_pname_count(value);
4950 process_entrypoint_error("%s: Can't determine count of GL value 0x%08X\n", VOGL_METHOD_NAME, value);
4951 return cStatusSoftFailure;
4955 vogl::growable_array<GLint, 16> data(n + 1);
4956 data[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
4958 GL_ENTRYPOINT(glGetBufferParameteriv)(target, value, data.get_ptr());
4960 VOGL_VERIFY(data[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
4962 GLint trace_data = pTrace_data ? pTrace_data[0] : -1;
4963 if (data[0] != trace_data)
4965 process_entrypoint_warning("%s: Replay's returned GLint differed from trace's!\n", VOGL_METHOD_NAME);
4966 vogl_warning_printf("Trace data: %i, Replay data: %i\n", trace_data, data[0]);
4974 case VOGL_ENTRYPOINT_glGetBufferPointerv:
4976 if (!benchmark_mode())
4978 GLvoid *pReplay_ptr = NULL;
4979 GL_ENTRYPOINT(glGetBufferPointerv)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLenum>(1), &pReplay_ptr);
4981 vogl_client_memory_array trace_void_ptr_array = trace_packet.get_param_client_memory_array(2);
4982 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;
4984 if ((pReplay_ptr != NULL) != (first_trace_ptr != 0))
4986 process_entrypoint_warning("%s: First replay's returned GLvoid* differed from trace's!\n", VOGL_METHOD_NAME);
4987 vogl_warning_printf("Trace: 0x%" PRIx64 ", Replay: 0x%" PRIx64 "\n", first_trace_ptr, reinterpret_cast<uint64_t>(pReplay_ptr));
4993 case VOGL_ENTRYPOINT_glShaderSource:
4994 case VOGL_ENTRYPOINT_glShaderSourceARB:
4996 const status_t status = handle_ShaderSource(trace_packet.get_param_value<GLhandleARB>(0),
4997 trace_packet.get_param_value<GLsizei>(1),
4998 trace_packet.get_param_client_memory_array(2),
4999 trace_packet.get_param_client_memory<const GLint>(3));
5000 if (status != cStatusOK)
5004 case VOGL_ENTRYPOINT_glGetProgramInfoLog:
5006 GLuint trace_object = trace_packet.get_param_value<GLuint>(0);
5007 GLuint replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5010 GL_ENTRYPOINT(glGetProgramiv)(replay_object, GL_INFO_LOG_LENGTH, &length);
5013 process_entrypoint_error("%s: Failed retrieving info log length for trace object %u, reply object %u\n", VOGL_METHOD_NAME, trace_object, replay_object);
5014 return cStatusSoftFailure;
5018 vogl::vector<GLchar> log(length);
5020 GLsizei actual_length = 0;
5021 GL_ENTRYPOINT(glGetProgramInfoLog)(replay_object, length, &actual_length, log.get_ptr());
5025 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());
5031 case VOGL_ENTRYPOINT_glGetPointerv:
5033 if (!benchmark_mode())
5036 GL_ENTRYPOINT(glGetPointerv)(trace_packet.get_param_value<GLenum>(0), &ptr);
5038 // TODO: Differ vs. trace's in some way?
5043 case VOGL_ENTRYPOINT_glGetInfoLogARB:
5045 GLhandleARB trace_object = trace_packet.get_param_value<GLhandleARB>(0);
5046 GLhandleARB replay_object = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_object);
5048 GLsizei length = -1;
5049 GL_ENTRYPOINT(glGetObjectParameterivARB)(replay_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &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<GLcharARB> log(length);
5059 GLsizei actual_length = 0;
5060 GL_ENTRYPOINT(glGetInfoLogARB)(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_glGetUniformLocation:
5072 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5073 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5074 GLint trace_loc = trace_packet.get_return_value<GLint>();
5078 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5080 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocation)(replay_handle, pName);
5084 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);
5089 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);
5092 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5093 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5094 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5096 glsl_program_state &state = it->second;
5097 state.m_uniform_locations.erase(trace_loc);
5098 state.m_uniform_locations.insert(trace_loc, replay_loc);
5105 case VOGL_ENTRYPOINT_glGetUniformLocationARB:
5107 GLhandleARB trace_handle = trace_packet.get_param_value<GLhandleARB>(0);
5108 GLhandleARB replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5109 GLint trace_loc = trace_packet.get_return_value<GLint>();
5113 const GLcharARB *pName = trace_packet.get_param_client_memory<GLcharARB>(1);
5115 GLint replay_loc = GL_ENTRYPOINT(glGetUniformLocationARB)(replay_handle, pName);
5119 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);
5124 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);
5127 glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_handle);
5128 if (it == get_shared_state()->m_glsl_program_hash_map.end())
5129 it = get_shared_state()->m_glsl_program_hash_map.insert(trace_handle).first;
5131 glsl_program_state &state = it->second;
5132 state.m_uniform_locations.erase(trace_loc);
5133 state.m_uniform_locations.insert(trace_loc, replay_loc);
5140 case VOGL_ENTRYPOINT_glGetActiveAttrib:
5141 case VOGL_ENTRYPOINT_glGetActiveUniform:
5143 if (!benchmark_mode())
5145 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5146 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5148 GLuint index = trace_packet.get_param_value<GLuint>(1);
5149 GLsizei bufSize = trace_packet.get_param_value<GLsizei>(2);
5151 GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(3);
5152 GLint *pTrace_size = trace_packet.get_param_client_memory<GLint>(4);
5153 GLenum *pTrace_type = trace_packet.get_param_client_memory<GLenum>(5);
5154 GLchar *pTrace_name = trace_packet.get_param_client_memory<GLchar>(6);
5156 vogl::growable_array<GLchar, 1024> name_buf(bufSize + 1); // + 1 guarantees non-empty and null terminated
5162 if (entrypoint_id == VOGL_ENTRYPOINT_glGetActiveAttrib)
5163 GL_ENTRYPOINT(glGetActiveAttrib)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5165 GL_ENTRYPOINT(glGetActiveUniform)(replay_handle, index, bufSize, &len, &size, &type, name_buf.get_ptr());
5167 bool mismatch = false;
5169 GLsizei trace_len = 0;
5172 trace_len = pTrace_length[0];
5173 if (trace_len != len)
5177 GLint trace_size = 0;
5180 trace_size = pTrace_size[0];
5181 if (trace_size != size)
5185 GLenum trace_type = 0;
5188 trace_type = pTrace_type[0];
5189 if (trace_type != type)
5193 if ((bufSize) && (pTrace_name))
5195 uint n = vogl_strlen((const char *)pTrace_name) + 1;
5196 if (bufSize < (GLsizei)n)
5198 else if (memcmp(name_buf.get_ptr(), pTrace_name, n) != 0)
5204 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5205 vogl_warning_printf("Trace handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5206 (uint)trace_handle, (uint)index, (uint)bufSize, (uint)trace_len, (uint)trace_type, (pTrace_name != NULL) ? (const char *)pTrace_name : "");
5207 vogl_warning_printf("GL handle: %u, index: %u, bufSize: %u, trace_len: %u, trace_type: %u, name: %s\n",
5208 (uint)replay_handle, (uint)index, (uint)bufSize, (uint)len, (uint)type, name_buf.get_ptr());
5214 case VOGL_ENTRYPOINT_glGetAttachedShaders:
5216 if (!benchmark_mode())
5218 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5219 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5221 GLsizei max_count = trace_packet.get_param_value<GLsizei>(1);
5223 vogl::growable_array<GLuint, 16> shaders(max_count);
5225 GL_ENTRYPOINT(glGetAttachedShaders)(replay_handle, trace_packet.get_param_value<GLsizei>(1), &count, shaders.get_ptr());
5227 // TODO: Diff results
5232 case VOGL_ENTRYPOINT_glGetAttribLocation:
5234 if (!benchmark_mode())
5236 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5237 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5239 const GLchar *pName = trace_packet.get_param_client_memory<GLchar>(1);
5241 GLint replay_result = GL_ENTRYPOINT(glGetAttribLocation)(replay_handle, pName);
5242 GLint trace_result = trace_packet.get_return_value<GLint>();
5244 if (replay_result != trace_result)
5246 process_entrypoint_warning("%s: Replay of %s returned data differed from trace's\n", VOGL_METHOD_NAME, trace_packet.get_entrypoint_desc().m_pName);
5247 vogl_warning_printf("Trace value: %i, replay: %i\n", trace_result, replay_result);
5253 case VOGL_ENTRYPOINT_glGetProgramivARB:
5255 if (!benchmark_mode())
5257 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5258 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5259 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5260 uint params_count = params_size / sizeof(GLint);
5262 int n = g_gl_enums.get_pname_count(pname);
5265 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5266 return cStatusSoftFailure;
5270 vogl::growable_array<GLint, 16> params(n + 1);
5271 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5273 GL_ENTRYPOINT(glGetProgramivARB)(
5274 trace_packet.get_param_value<GLenum>(0),
5278 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5280 if (params_count != static_cast<uint>(n))
5282 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5284 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5286 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));
5293 case VOGL_ENTRYPOINT_glGetProgramiv:
5295 if (!benchmark_mode())
5297 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5298 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5300 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5302 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
5303 uint params_size = trace_packet.get_param_client_memory_data_size(2);
5304 uint params_count = params_size / sizeof(GLint);
5306 int n = g_gl_enums.get_pname_count(pname);
5309 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5310 return cStatusSoftFailure;
5314 vogl::growable_array<GLint, 16> params(n + 1);
5315 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5317 GL_ENTRYPOINT(glGetProgramiv)(
5322 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5324 if (params_count != static_cast<uint>(n))
5326 process_entrypoint_warning("%s: Size of replay's params array differs from trace's\n", VOGL_METHOD_NAME);
5328 else if (pParams && memcmp(pParams, params.get_ptr(), n * sizeof(GLint)) != 0)
5330 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));
5337 case VOGL_ENTRYPOINT_glLinkProgram:
5338 case VOGL_ENTRYPOINT_glLinkProgramARB:
5339 case VOGL_ENTRYPOINT_glProgramBinary:
5341 handle_link_program(entrypoint_id);
5345 case VOGL_ENTRYPOINT_glCompileShader:
5347 GL_ENTRYPOINT(glCompileShader)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLuint>(0)));
5350 case VOGL_ENTRYPOINT_glCompileShaderARB:
5352 GL_ENTRYPOINT(glCompileShaderARB)(map_handle(get_shared_state()->m_shadow_state.m_objs, trace_packet.get_param_value<GLhandleARB>(0)));
5355 case VOGL_ENTRYPOINT_glGetShaderiv:
5357 if (!benchmark_mode())
5359 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5360 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5362 GLenum pname = trace_packet.get_param_value<GLenum>(1);
5365 const GLint *pClient_params = trace_packet.get_param_client_memory<GLint>(2);
5367 GL_ENTRYPOINT(glGetShaderiv)(replay_handle, pname, ¶ms);
5369 if ((pClient_params) && (*pClient_params != params))
5371 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
5372 vogl_warning_printf("Trace data: %i, Replay data: %i\n", pClient_params ? *pClient_params : 0, params);
5378 case VOGL_ENTRYPOINT_glGetShaderInfoLog:
5380 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
5381 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
5383 GLsizei trace_max_length = trace_packet.get_param_value<GLsizei>(1);
5384 const GLsizei *pTrace_length = trace_packet.get_param_client_memory<GLsizei>(2);
5385 VOGL_NOTE_UNUSED(pTrace_length);
5386 const GLchar *pTrace_info_log = trace_packet.get_param_client_memory<GLchar>(3);
5387 VOGL_NOTE_UNUSED(pTrace_info_log);
5389 vogl::growable_array<GLchar, 512> log(trace_max_length);
5391 GL_ENTRYPOINT(glGetShaderInfoLog)(replay_handle, trace_max_length, &length, log.get_ptr());
5395 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());
5400 case VOGL_ENTRYPOINT_glGetBooleanv:
5402 if (!benchmark_mode())
5404 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5405 const GLboolean *pParams = trace_packet.get_param_client_memory<GLboolean>(1);
5407 int n = g_gl_enums.get_pname_count(pname);
5410 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));
5411 return cStatusSoftFailure;
5415 vogl::growable_array<GLboolean, 16> params(n + 1);
5416 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC;
5418 GL_ENTRYPOINT(glGetBooleanv)(pname, params.get_ptr());
5420 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_BYTE_MAGIC);
5422 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLboolean)) != 0)
5424 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));
5431 case VOGL_ENTRYPOINT_glGetDoublev:
5433 if (!benchmark_mode())
5435 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5436 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(1);
5438 int n = g_gl_enums.get_pname_count(pname);
5441 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5442 return cStatusSoftFailure;
5446 vogl::growable_array<GLdouble, 17> params(n + 1);
5447 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5449 GL_ENTRYPOINT(glGetDoublev)(pname, params.get_ptr());
5451 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5453 if (memcmp(pParams, params.get_ptr(), n * sizeof(GLdouble)) != 0)
5455 process_entrypoint_warning("%s: Replay's returned GLdouble data differed from trace's\n", VOGL_METHOD_NAME);
5462 case VOGL_ENTRYPOINT_glGetFloatv:
5464 if (!benchmark_mode())
5466 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5467 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<GLfloat>(1);
5468 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLfloat);
5470 int n = g_gl_enums.get_pname_count(pname);
5473 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5474 return cStatusSoftFailure;
5477 vogl::growable_array<GLfloat, 17> params(n + 1);
5478 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
5480 GL_ENTRYPOINT(glGetFloatv)(pname, params.get_ptr());
5482 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
5484 if (static_cast<int>(trace_params_count) < n)
5485 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5486 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLfloat)) != 0)
5488 process_entrypoint_warning("%s: Replay's returned GLfloat data differed from trace's\n", VOGL_METHOD_NAME);
5494 case VOGL_ENTRYPOINT_glGetIntegerv:
5496 if (!benchmark_mode())
5498 GLenum pname = trace_packet.get_param_value<GLenum>(0);
5499 const GLint *pTrace_params = trace_packet.get_param_client_memory<GLint>(1);
5500 uint trace_params_count = trace_packet.get_param_client_memory_data_size(1) / sizeof(GLint);
5502 int n = g_gl_enums.get_pname_count(pname);
5505 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
5506 return cStatusSoftFailure;
5509 vogl::growable_array<GLint, 16> params(n + 1);
5510 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
5512 GL_ENTRYPOINT(glGetIntegerv)(pname, params.get_ptr());
5514 VOGL_VERIFY(params[n] == (GLint)VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
5516 bool is_binding = false;
5519 case GL_ARRAY_BUFFER_BINDING:
5520 case GL_COLOR_ARRAY_BUFFER_BINDING:
5521 case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
5522 case GL_DRAW_FRAMEBUFFER_BINDING:
5523 case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
5524 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5525 case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
5526 case GL_INDEX_ARRAY_BUFFER_BINDING:
5527 case GL_NORMAL_ARRAY_BUFFER_BINDING:
5528 case GL_PIXEL_PACK_BUFFER_BINDING:
5529 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5530 case GL_PROGRAM_PIPELINE_BINDING:
5531 case GL_READ_FRAMEBUFFER_BINDING:
5532 case GL_RENDERBUFFER_BINDING:
5533 case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
5534 case GL_SHADER_STORAGE_BUFFER_BINDING:
5535 case GL_TEXTURE_BINDING_1D:
5536 case GL_TEXTURE_BINDING_1D_ARRAY:
5537 case GL_TEXTURE_BINDING_2D:
5538 case GL_TEXTURE_BINDING_2D_ARRAY:
5539 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
5540 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
5541 case GL_TEXTURE_BINDING_3D:
5542 case GL_TEXTURE_BINDING_BUFFER:
5543 case GL_TEXTURE_BINDING_CUBE_MAP:
5544 case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
5545 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5546 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
5547 case GL_UNIFORM_BUFFER_BINDING:
5548 case GL_VERTEX_ARRAY_BINDING:
5549 case GL_VERTEX_ARRAY_BUFFER_BINDING:
5550 case GL_CURRENT_PROGRAM:
5559 // Don't bother diffing bindings, the trace's are in the trace domain while the glGet's results are in the replay domain.
5562 if (static_cast<int>(trace_params_count) < n)
5564 process_entrypoint_warning("%s: Replay param array size (%u) does not match the expected size (%u)\n", VOGL_METHOD_NAME, trace_params_count, n);
5566 else if (memcmp(pTrace_params, params.get_ptr(), n * sizeof(GLint)) != 0)
5568 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));
5569 for (int i = 0; i < n; i++)
5570 vogl_printf("GLint %u: Trace: %i, Replay: %i\n", i, pTrace_params[i], params[i]);
5577 // glProgramUniform's
5578 case VOGL_ENTRYPOINT_glProgramUniform1f:
5580 set_program_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glProgramUniform1f));
5583 case VOGL_ENTRYPOINT_glProgramUniform1i:
5585 set_program_uniform_helper1<GLint>(GL_ENTRYPOINT(glProgramUniform1i));
5588 case VOGL_ENTRYPOINT_glProgramUniform1ui:
5590 set_program_uniform_helper1<GLuint>(GL_ENTRYPOINT(glProgramUniform1ui));
5593 case VOGL_ENTRYPOINT_glProgramUniform2f:
5595 set_program_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glProgramUniform2f));
5598 case VOGL_ENTRYPOINT_glProgramUniform2i:
5600 set_program_uniform_helper2<GLint>(GL_ENTRYPOINT(glProgramUniform2i));
5603 case VOGL_ENTRYPOINT_glProgramUniform2ui:
5605 set_program_uniform_helper2<GLuint>(GL_ENTRYPOINT(glProgramUniform2ui));
5608 case VOGL_ENTRYPOINT_glProgramUniform3f:
5610 set_program_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glProgramUniform3f));
5613 case VOGL_ENTRYPOINT_glProgramUniform3i:
5615 set_program_uniform_helper3<GLint>(GL_ENTRYPOINT(glProgramUniform3i));
5618 case VOGL_ENTRYPOINT_glProgramUniform3ui:
5620 set_program_uniform_helper3<GLuint>(GL_ENTRYPOINT(glProgramUniform3ui));
5623 case VOGL_ENTRYPOINT_glProgramUniform4f:
5625 set_program_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glProgramUniform4f));
5628 case VOGL_ENTRYPOINT_glProgramUniform4i:
5630 set_program_uniform_helper4<GLint>(GL_ENTRYPOINT(glProgramUniform4i));
5633 case VOGL_ENTRYPOINT_glProgramUniform4ui:
5635 set_program_uniform_helper4<GLuint>(GL_ENTRYPOINT(glProgramUniform4ui));
5638 case VOGL_ENTRYPOINT_glProgramUniform1fv:
5640 set_program_uniformv_helper<1, float>(GL_ENTRYPOINT(glProgramUniform1fv));
5643 case VOGL_ENTRYPOINT_glProgramUniform2fv:
5645 set_program_uniformv_helper<2, float>(GL_ENTRYPOINT(glProgramUniform2fv));
5648 case VOGL_ENTRYPOINT_glProgramUniform3fv:
5650 set_program_uniformv_helper<3, float>(GL_ENTRYPOINT(glProgramUniform3fv));
5653 case VOGL_ENTRYPOINT_glProgramUniform4fv:
5655 set_program_uniformv_helper<4, float>(GL_ENTRYPOINT(glProgramUniform4fv));
5658 case VOGL_ENTRYPOINT_glProgramUniform1iv:
5660 set_program_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glProgramUniform1iv));
5663 case VOGL_ENTRYPOINT_glProgramUniform2iv:
5665 set_program_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glProgramUniform2iv));
5668 case VOGL_ENTRYPOINT_glProgramUniform3iv:
5670 set_program_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glProgramUniform3iv));
5673 case VOGL_ENTRYPOINT_glProgramUniform4iv:
5675 set_program_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glProgramUniform4iv));
5678 case VOGL_ENTRYPOINT_glProgramUniform1uiv:
5680 set_program_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glProgramUniform1uiv));
5683 case VOGL_ENTRYPOINT_glProgramUniform2uiv:
5685 set_program_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glProgramUniform2uiv));
5688 case VOGL_ENTRYPOINT_glProgramUniform3uiv:
5690 set_program_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glProgramUniform3uiv));
5693 case VOGL_ENTRYPOINT_glProgramUniform4uiv:
5695 set_program_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glProgramUniform4uiv));
5698 case VOGL_ENTRYPOINT_glProgramUniformMatrix2fv:
5700 set_program_uniform_matrixv_helper<2, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix2fv));
5703 case VOGL_ENTRYPOINT_glProgramUniformMatrix3fv:
5705 set_program_uniform_matrixv_helper<3, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix3fv));
5708 case VOGL_ENTRYPOINT_glProgramUniformMatrix4fv:
5710 set_program_uniform_matrixv_helper<4, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix4fv));
5713 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x3fv:
5715 set_program_uniform_matrixv_helper<2, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x3fv));
5718 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x2fv:
5720 set_program_uniform_matrixv_helper<3, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x2fv));
5723 case VOGL_ENTRYPOINT_glProgramUniformMatrix2x4fv:
5725 set_program_uniform_matrixv_helper<2, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix2x4fv));
5728 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x2fv:
5730 set_program_uniform_matrixv_helper<4, 2, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x2fv));
5733 case VOGL_ENTRYPOINT_glProgramUniformMatrix3x4fv:
5735 set_program_uniform_matrixv_helper<3, 4, float>(GL_ENTRYPOINT(glProgramUniformMatrix3x4fv));
5738 case VOGL_ENTRYPOINT_glProgramUniformMatrix4x3fv:
5740 set_program_uniform_matrixv_helper<4, 3, float>(GL_ENTRYPOINT(glProgramUniformMatrix4x3fv));
5744 case VOGL_ENTRYPOINT_glUniform1f:
5746 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1f));
5749 case VOGL_ENTRYPOINT_glUniform1fARB:
5751 set_uniform_helper1<GLfloat>(GL_ENTRYPOINT(glUniform1fARB));
5754 case VOGL_ENTRYPOINT_glUniform2f:
5756 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2f));
5759 case VOGL_ENTRYPOINT_glUniform2fARB:
5761 set_uniform_helper2<GLfloat>(GL_ENTRYPOINT(glUniform2fARB));
5764 case VOGL_ENTRYPOINT_glUniform3f:
5766 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3f));
5769 case VOGL_ENTRYPOINT_glUniform3fARB:
5771 set_uniform_helper3<GLfloat>(GL_ENTRYPOINT(glUniform3fARB));
5774 case VOGL_ENTRYPOINT_glUniform4f:
5776 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4f));
5779 case VOGL_ENTRYPOINT_glUniform4fARB:
5781 set_uniform_helper4<GLfloat>(GL_ENTRYPOINT(glUniform4fARB));
5784 case VOGL_ENTRYPOINT_glUniform1i:
5786 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1i));
5789 case VOGL_ENTRYPOINT_glUniform1iARB:
5791 set_uniform_helper1<GLint>(GL_ENTRYPOINT(glUniform1iARB));
5794 case VOGL_ENTRYPOINT_glUniform2i:
5796 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2i));
5799 case VOGL_ENTRYPOINT_glUniform2iARB:
5801 set_uniform_helper2<GLint>(GL_ENTRYPOINT(glUniform2iARB));
5804 case VOGL_ENTRYPOINT_glUniform3i:
5806 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3i));
5809 case VOGL_ENTRYPOINT_glUniform3iARB:
5811 set_uniform_helper3<GLint>(GL_ENTRYPOINT(glUniform3iARB));
5814 case VOGL_ENTRYPOINT_glUniform4i:
5816 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4i));
5819 case VOGL_ENTRYPOINT_glUniform4iARB:
5821 set_uniform_helper4<GLint>(GL_ENTRYPOINT(glUniform4iARB));
5824 case VOGL_ENTRYPOINT_glUniform1ui:
5826 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1ui));
5829 case VOGL_ENTRYPOINT_glUniform1uiEXT:
5831 set_uniform_helper1<GLuint>(GL_ENTRYPOINT(glUniform1uiEXT));
5834 case VOGL_ENTRYPOINT_glUniform2ui:
5836 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2ui));
5839 case VOGL_ENTRYPOINT_glUniform2uiEXT:
5841 set_uniform_helper2<GLuint>(GL_ENTRYPOINT(glUniform2uiEXT));
5844 case VOGL_ENTRYPOINT_glUniform3ui:
5846 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3ui));
5849 case VOGL_ENTRYPOINT_glUniform3uiEXT:
5851 set_uniform_helper3<GLuint>(GL_ENTRYPOINT(glUniform3uiEXT));
5854 case VOGL_ENTRYPOINT_glUniform4ui:
5856 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4ui));
5859 case VOGL_ENTRYPOINT_glUniform4uiEXT:
5861 set_uniform_helper4<GLuint>(GL_ENTRYPOINT(glUniform4uiEXT));
5864 case VOGL_ENTRYPOINT_glUniform1uiv:
5866 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uiv));
5869 case VOGL_ENTRYPOINT_glUniform1uivEXT:
5871 set_uniformv_helper<1, GLuint>(GL_ENTRYPOINT(glUniform1uivEXT));
5874 case VOGL_ENTRYPOINT_glUniform2uiv:
5876 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uiv));
5879 case VOGL_ENTRYPOINT_glUniform2uivEXT:
5881 set_uniformv_helper<2, GLuint>(GL_ENTRYPOINT(glUniform2uivEXT));
5884 case VOGL_ENTRYPOINT_glUniform3uiv:
5886 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uiv));
5889 case VOGL_ENTRYPOINT_glUniform3uivEXT:
5891 set_uniformv_helper<3, GLuint>(GL_ENTRYPOINT(glUniform3uivEXT));
5894 case VOGL_ENTRYPOINT_glUniform4uiv:
5896 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uiv));
5899 case VOGL_ENTRYPOINT_glUniform4uivEXT:
5901 set_uniformv_helper<4, GLuint>(GL_ENTRYPOINT(glUniform4uivEXT));
5904 case VOGL_ENTRYPOINT_glUniform1iv:
5906 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1iv));
5909 case VOGL_ENTRYPOINT_glUniform1ivARB:
5911 set_uniformv_helper<1, GLint>(GL_ENTRYPOINT(glUniform1ivARB));
5914 case VOGL_ENTRYPOINT_glUniform2iv:
5916 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2iv));
5919 case VOGL_ENTRYPOINT_glUniform2ivARB:
5921 set_uniformv_helper<2, GLint>(GL_ENTRYPOINT(glUniform2ivARB));
5924 case VOGL_ENTRYPOINT_glUniform3iv:
5926 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3iv));
5929 case VOGL_ENTRYPOINT_glUniform3ivARB:
5931 set_uniformv_helper<3, GLint>(GL_ENTRYPOINT(glUniform3ivARB));
5934 case VOGL_ENTRYPOINT_glUniform4iv:
5936 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4iv));
5939 case VOGL_ENTRYPOINT_glUniform4ivARB:
5941 set_uniformv_helper<4, GLint>(GL_ENTRYPOINT(glUniform4ivARB));
5944 case VOGL_ENTRYPOINT_glUniform1fv:
5946 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fv));
5949 case VOGL_ENTRYPOINT_glUniform1fvARB:
5951 set_uniformv_helper<1, GLfloat>(GL_ENTRYPOINT(glUniform1fvARB));
5954 case VOGL_ENTRYPOINT_glUniform2fv:
5956 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fv));
5959 case VOGL_ENTRYPOINT_glUniform2fvARB:
5961 set_uniformv_helper<2, GLfloat>(GL_ENTRYPOINT(glUniform2fvARB));
5964 case VOGL_ENTRYPOINT_glUniform3fv:
5966 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fv));
5969 case VOGL_ENTRYPOINT_glUniform3fvARB:
5971 set_uniformv_helper<3, GLfloat>(GL_ENTRYPOINT(glUniform3fvARB));
5974 case VOGL_ENTRYPOINT_glUniform4fv:
5976 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fv));
5979 case VOGL_ENTRYPOINT_glUniform4fvARB:
5981 set_uniformv_helper<4, GLfloat>(GL_ENTRYPOINT(glUniform4fvARB));
5984 case VOGL_ENTRYPOINT_glUniformMatrix2fvARB:
5986 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fvARB));
5989 case VOGL_ENTRYPOINT_glUniformMatrix2fv:
5991 set_uniform_matrixv_helper<2, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2fv));
5994 case VOGL_ENTRYPOINT_glUniformMatrix3fvARB:
5996 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fvARB));
5999 case VOGL_ENTRYPOINT_glUniformMatrix3fv:
6001 set_uniform_matrixv_helper<3, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3fv));
6004 case VOGL_ENTRYPOINT_glUniformMatrix4fvARB:
6006 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fvARB));
6009 case VOGL_ENTRYPOINT_glUniformMatrix4fv:
6011 set_uniform_matrixv_helper<4, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4fv));
6014 case VOGL_ENTRYPOINT_glUniformMatrix2x3fv:
6016 set_uniform_matrixv_helper<2, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x3fv));
6019 case VOGL_ENTRYPOINT_glUniformMatrix3x2fv:
6021 set_uniform_matrixv_helper<3, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x2fv));
6024 case VOGL_ENTRYPOINT_glUniformMatrix2x4fv:
6026 set_uniform_matrixv_helper<2, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix2x4fv));
6029 case VOGL_ENTRYPOINT_glUniformMatrix4x2fv:
6031 set_uniform_matrixv_helper<4, 2, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x2fv));
6034 case VOGL_ENTRYPOINT_glUniformMatrix3x4fv:
6036 set_uniform_matrixv_helper<3, 4, GLfloat>(GL_ENTRYPOINT(glUniformMatrix3x4fv));
6039 case VOGL_ENTRYPOINT_glUniformMatrix4x3fv:
6041 set_uniform_matrixv_helper<4, 3, GLfloat>(GL_ENTRYPOINT(glUniformMatrix4x3fv));
6044 case VOGL_ENTRYPOINT_glBeginQuery:
6045 case VOGL_ENTRYPOINT_glBeginQueryARB:
6047 GLenum target = trace_packet.get_param_value<GLenum>(0);
6048 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6049 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6051 if (!m_pCur_context_state->m_inside_gl_begin)
6054 if (entrypoint_id == VOGL_ENTRYPOINT_glBeginQuery)
6055 GL_ENTRYPOINT(glBeginQuery)(target, replay_handle);
6057 GL_ENTRYPOINT(glBeginQueryARB)(target, replay_handle);
6059 if ((replay_handle) && (!m_pCur_context_state->m_inside_gl_begin) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6061 if (check_gl_error())
6062 return cStatusGLError;
6064 get_shared_state()->m_query_targets[replay_handle] = target;
6069 case VOGL_ENTRYPOINT_glEndQuery:
6071 GL_ENTRYPOINT(glEndQuery)(trace_packet.get_param_value<GLenum>(0));
6074 case VOGL_ENTRYPOINT_glEndQueryARB:
6076 GL_ENTRYPOINT(glEndQueryARB)(trace_packet.get_param_value<GLenum>(0));
6079 case VOGL_ENTRYPOINT_glGetQueryObjectiv:
6081 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6082 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6084 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6086 int n = g_gl_enums.get_pname_count(pname);
6089 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6090 return cStatusSoftFailure;
6094 vogl::growable_array<GLint, 16> params(n + 1);
6095 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6097 GL_ENTRYPOINT(glGetQueryObjectiv)(replay_handle, pname, params.get_ptr());
6099 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6104 case VOGL_ENTRYPOINT_glGetQueryObjectivARB:
6106 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6107 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6109 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6111 int n = g_gl_enums.get_pname_count(pname);
6114 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6115 return cStatusSoftFailure;
6119 vogl::growable_array<GLint, 16> params(n + 1);
6120 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6122 GL_ENTRYPOINT(glGetQueryObjectivARB)(replay_handle, pname, params.get_ptr());
6124 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6129 case VOGL_ENTRYPOINT_glGetQueryObjectuiv:
6131 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6132 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6134 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6136 int n = g_gl_enums.get_pname_count(pname);
6139 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6140 return cStatusSoftFailure;
6144 vogl::growable_array<GLuint, 16> params(n + 1);
6145 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6147 GL_ENTRYPOINT(glGetQueryObjectuiv)(replay_handle, pname, params.get_ptr());
6149 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6154 case VOGL_ENTRYPOINT_glGetQueryObjectuivARB:
6156 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
6157 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
6159 GLenum pname = trace_packet.get_param_value<GLenum>(1);
6161 int n = g_gl_enums.get_pname_count(pname);
6164 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6165 return cStatusSoftFailure;
6169 vogl::growable_array<GLuint, 16> params(n + 1);
6170 params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6172 GL_ENTRYPOINT(glGetQueryObjectuivARB)(replay_handle, pname, params.get_ptr());
6174 VOGL_VERIFY(params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6179 case VOGL_ENTRYPOINT_glQueryCounter:
6181 VOGL_REPLAY_LOAD_PARAMS_HELPER_glQueryCounter;
6183 id = map_handle(get_shared_state()->m_queries, id);
6185 VOGL_REPLAY_CALL_GL_HELPER_glQueryCounter;
6189 case VOGL_ENTRYPOINT_glGetQueryObjecti64v:
6191 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjecti64v;
6192 VOGL_NOTE_UNUSED(pTrace_params);
6194 id = map_handle(get_shared_state()->m_queries, id);
6196 int n = g_gl_enums.get_pname_count(pname);
6199 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6200 return cStatusSoftFailure;
6203 vogl::growable_array<GLint64, 16> temp_params(n + 1);
6204 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6206 GLint64 *pReplay_params = temp_params.get_ptr();
6208 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjecti64v;
6210 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6214 case VOGL_ENTRYPOINT_glGetQueryObjectui64v:
6216 VOGL_REPLAY_LOAD_PARAMS_HELPER_glGetQueryObjectui64v;
6217 VOGL_NOTE_UNUSED(pTrace_params);
6219 id = map_handle(get_shared_state()->m_queries, id);
6221 int n = g_gl_enums.get_pname_count(pname);
6224 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
6225 return cStatusSoftFailure;
6228 vogl::growable_array<GLuint64, 16> temp_params(n + 1);
6229 temp_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
6231 GLuint64 *pReplay_params = temp_params.get_ptr();
6233 VOGL_REPLAY_CALL_GL_HELPER_glGetQueryObjectui64v;
6235 VOGL_VERIFY(temp_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
6239 case VOGL_ENTRYPOINT_glBindBuffer:
6240 case VOGL_ENTRYPOINT_glBindBufferARB:
6242 GLenum target = trace_packet.get_param_value<GLenum>(0);
6243 GLuint trace_handle = trace_packet.get_param_value<GLuint>(1);
6244 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
6248 SWITCH_GL_ENTRYPOINT2_VOID(glBindBuffer, glBindBufferARB, target, replay_handle);
6250 if (check_gl_error())
6251 return cStatusGLError;
6253 if ((trace_handle) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6255 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_handle);
6257 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_handle);
6258 else if (*pBinding == GL_NONE)
6264 case VOGL_ENTRYPOINT_glBindBufferBase:
6265 case VOGL_ENTRYPOINT_glBindBufferBaseEXT:
6266 case VOGL_ENTRYPOINT_glBindBufferBaseNV:
6268 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferBase;
6270 GLuint trace_buffer = buffer;
6271 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6275 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseNV)
6276 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseNV;
6277 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferBaseEXT)
6278 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBaseEXT;
6280 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferBase;
6282 if (check_gl_error())
6283 return cStatusGLError;
6285 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6287 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6289 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6290 else if (*pBinding == GL_NONE)
6296 case VOGL_ENTRYPOINT_glBindBufferRange:
6297 case VOGL_ENTRYPOINT_glBindBufferRangeEXT:
6298 case VOGL_ENTRYPOINT_glBindBufferRangeNV:
6300 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBindBufferRange;
6302 GLuint trace_buffer = buffer;
6303 buffer = map_handle(get_shared_state()->m_buffers, buffer);
6307 if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeNV)
6308 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeNV;
6309 else if (entrypoint_id == VOGL_ENTRYPOINT_glBindBufferRangeEXT)
6310 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRangeEXT;
6312 VOGL_REPLAY_CALL_GL_HELPER_glBindBufferRange;
6314 if (check_gl_error())
6315 return cStatusGLError;
6317 if ((trace_buffer) && (get_context_state()->m_current_display_list_mode != GL_COMPILE))
6319 GLuint *pBinding = get_shared_state()->m_buffer_targets.find_value(trace_buffer);
6321 process_entrypoint_error("%s: Couldn't find trace buffer handle 0x%X in buffer target map!\n", VOGL_METHOD_NAME, trace_buffer);
6322 else if (*pBinding == GL_NONE)
6328 case VOGL_ENTRYPOINT_glFenceSync:
6330 vogl_sync_ptr_value trace_handle = trace_packet.get_return_ptr_value();
6333 GLsync replay_handle = GL_ENTRYPOINT(glFenceSync)(trace_packet.get_param_value<GLenum>(0), trace_packet.get_param_value<GLbitfield>(1));
6336 process_entrypoint_error("%s: glFenceSync on trace handle 0x%" PRIX64 " succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME, trace_handle);
6337 return cStatusHardFailure;
6341 get_shared_state()->m_syncs.insert(trace_handle, replay_handle);
6347 case VOGL_ENTRYPOINT_glWaitSync:
6348 case VOGL_ENTRYPOINT_glClientWaitSync:
6350 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6351 GLsync replay_sync = NULL;
6353 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6354 if (it == get_shared_state()->m_syncs.end())
6358 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6359 return cStatusHardFailure;
6364 replay_sync = it->second;
6367 if (entrypoint_id == VOGL_ENTRYPOINT_glWaitSync)
6368 GL_ENTRYPOINT(glWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6370 GL_ENTRYPOINT(glClientWaitSync)(replay_sync, trace_packet.get_param_value<GLbitfield>(1), trace_packet.get_param_value<GLuint64>(2));
6374 case VOGL_ENTRYPOINT_glDeleteSync:
6376 vogl_sync_ptr_value trace_sync = trace_packet.get_param_ptr_value(0);
6377 GLsync replay_sync = NULL;
6379 gl_sync_hash_map::const_iterator it = get_shared_state()->m_syncs.find(trace_sync);
6380 if (it == get_shared_state()->m_syncs.end())
6384 process_entrypoint_error("%s: Unable to map trace sync handle 0x%" PRIX64 " to GL handle\n", VOGL_METHOD_NAME, trace_sync);
6385 return cStatusHardFailure;
6390 replay_sync = it->second;
6393 GL_ENTRYPOINT(glDeleteSync)(replay_sync);
6397 get_shared_state()->m_syncs.erase(trace_sync);
6402 case VOGL_ENTRYPOINT_glVertexPointer:
6404 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),
6405 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6408 case VOGL_ENTRYPOINT_glVertexPointerEXT:
6410 VOGL_REPLAY_LOAD_PARAMS_HELPER_glVertexPointerEXT;
6411 VOGL_NOTE_UNUSED(pTrace_pointer);
6413 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]);
6416 case VOGL_ENTRYPOINT_glColorPointer:
6418 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),
6419 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6422 case VOGL_ENTRYPOINT_glColorPointerEXT:
6424 VOGL_REPLAY_LOAD_PARAMS_HELPER_glColorPointerEXT;
6425 VOGL_NOTE_UNUSED(pTrace_pointer);
6427 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]);
6430 case VOGL_ENTRYPOINT_glSecondaryColorPointer:
6432 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),
6433 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointer), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6436 case VOGL_ENTRYPOINT_glSecondaryColorPointerEXT:
6438 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),
6439 vogl_secondary_color_pointer_array_id, GL_ENTRYPOINT(glSecondaryColorPointerEXT), m_client_side_array_data[vogl_secondary_color_pointer_array_id]);
6442 case VOGL_ENTRYPOINT_glTexCoordPointer:
6444 GLint cur_client_active_texture = 0;
6445 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6447 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6448 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6450 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);
6451 return cStatusSoftFailure;
6454 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),
6455 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6458 case VOGL_ENTRYPOINT_glTexCoordPointerEXT:
6460 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexCoordPointerEXT;
6461 VOGL_NOTE_UNUSED(pTrace_pointer);
6463 GLint cur_client_active_texture = 0;
6464 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6466 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6467 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6469 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);
6470 return cStatusSoftFailure;
6473 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]);
6476 case VOGL_ENTRYPOINT_glFogCoordPointer:
6478 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),
6479 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointer));
6482 case VOGL_ENTRYPOINT_glFogCoordPointerEXT:
6484 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),
6485 vogl_fog_coord_pointer_array_id, GL_ENTRYPOINT(glFogCoordPointerEXT));
6488 case VOGL_ENTRYPOINT_glIndexPointer:
6490 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),
6491 vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointer));
6494 case VOGL_ENTRYPOINT_glIndexPointerEXT:
6496 VOGL_REPLAY_LOAD_PARAMS_HELPER_glIndexPointerEXT;
6497 VOGL_NOTE_UNUSED(pTrace_pointer);
6499 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_index_pointer_array_id, GL_ENTRYPOINT(glIndexPointerEXT));
6502 case VOGL_ENTRYPOINT_glNormalPointer:
6504 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),
6505 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6508 case VOGL_ENTRYPOINT_glNormalPointerEXT:
6510 VOGL_REPLAY_LOAD_PARAMS_HELPER_glNormalPointerEXT;
6511 VOGL_NOTE_UNUSED(pTrace_pointer);
6513 vertex_array_helper_no_size_count(type, stride, count, trace_packet.get_param_ptr_value(3), vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointerEXT));
6516 case VOGL_ENTRYPOINT_glEdgeFlagPointer:
6518 vertex_array_helper_no_type_no_size(trace_packet.get_param_value<GLsizei>(0), trace_packet.get_param_ptr_value(1),
6519 vogl_edge_flag_pointer_array_id, GL_ENTRYPOINT(glEdgeFlagPointer));
6522 case VOGL_ENTRYPOINT_glEdgeFlagPointerEXT:
6524 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEdgeFlagPointerEXT;
6525 VOGL_NOTE_UNUSED(pTrace_pointer);
6527 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));
6530 case VOGL_ENTRYPOINT_glInterleavedArrays:
6532 // TODO: Test this more!
6533 GLenum format = trace_packet.get_param_value<GLenum>(0);
6534 GLsizei stride = trace_packet.get_param_value<GLsizei>(1);
6535 const vogl_trace_ptr_value trace_pointer_value = trace_packet.get_param_ptr_value(2);
6538 for (fmt_index = 0; fmt_index < VOGL_INTERLEAVED_ARRAY_SIZE; fmt_index++)
6539 if (format == vogl_g_interleaved_array_descs[fmt_index].fmt)
6541 if (fmt_index == VOGL_INTERLEAVED_ARRAY_SIZE)
6543 process_entrypoint_error("%s: Invalid interleaved vertex format: 0x%X \n", VOGL_METHOD_NAME, format);
6544 return cStatusSoftFailure;
6549 process_entrypoint_error("%s: Invalid interleaved vertex stride: %i\n", VOGL_METHOD_NAME, static_cast<int>(stride));
6550 return cStatusSoftFailure;
6553 const interleaved_array_desc_entry_t &fmt = vogl_g_interleaved_array_descs[fmt_index];
6558 VOGL_ASSERT(stride > 0);
6561 GL_ENTRYPOINT(glDisableClientState)(GL_EDGE_FLAG_ARRAY);
6562 GL_ENTRYPOINT(glDisableClientState)(GL_INDEX_ARRAY);
6563 GL_ENTRYPOINT(glDisableClientState)(GL_SECONDARY_COLOR_ARRAY);
6564 GL_ENTRYPOINT(glDisableClientState)(GL_FOG_COORD_ARRAY);
6570 GLint cur_client_active_texture = 0;
6571 GL_ENTRYPOINT(glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE, &cur_client_active_texture);
6573 int tex_index = cur_client_active_texture - GL_TEXTURE0;
6574 if ((tex_index < 0) || (tex_index >= VOGL_MAX_SUPPORTED_GL_TEXCOORD_ARRAYS))
6576 process_entrypoint_error("%s: glInterleavedArrays called with an invalid or unsupported client active texture (0x%08X)\n", VOGL_METHOD_NAME, cur_client_active_texture);
6577 return cStatusSoftFailure;
6580 GL_ENTRYPOINT(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
6581 vertex_array_helper(fmt.st, GL_FLOAT, stride, trace_pointer_value,
6582 vogl_texcoord_pointer_array_id, GL_ENTRYPOINT(glTexCoordPointer), m_client_side_texcoord_data[tex_index]);
6586 GL_ENTRYPOINT(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
6593 GL_ENTRYPOINT(glEnableClientState)(GL_COLOR_ARRAY);
6594 vertex_array_helper(fmt.sc, fmt.tc, stride, trace_pointer_value + fmt.pc,
6595 vogl_color_pointer_array_id, GL_ENTRYPOINT(glColorPointer), m_client_side_array_data[vogl_color_pointer_array_id]);
6599 GL_ENTRYPOINT(glDisableClientState)(GL_COLOR_ARRAY);
6606 GL_ENTRYPOINT(glEnableClientState)(GL_NORMAL_ARRAY);
6607 vertex_array_helper_no_size(GL_FLOAT, stride, trace_pointer_value + fmt.pn,
6608 vogl_normal_pointer_array_id, GL_ENTRYPOINT(glNormalPointer));
6612 GL_ENTRYPOINT(glDisableClientState)(GL_NORMAL_ARRAY);
6617 GL_ENTRYPOINT(glEnableClientState)(GL_VERTEX_ARRAY);
6618 vertex_array_helper(fmt.sv, GL_FLOAT, stride, trace_pointer_value + fmt.pv,
6619 vogl_vertex_pointer_array_id, GL_ENTRYPOINT(glVertexPointer), m_client_side_array_data[vogl_vertex_pointer_array_id]);
6623 case VOGL_ENTRYPOINT_glVertexAttribIPointer:
6624 case VOGL_ENTRYPOINT_glVertexAttribIPointerEXT:
6626 GLuint index = trace_packet.get_param_value<GLuint>(0);
6627 GLint size = trace_packet.get_param_value<GLint>(1);
6628 GLenum type = trace_packet.get_param_value<GLenum>(2);
6629 GLsizei stride = trace_packet.get_param_value<GLsizei>(3);
6630 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(4);
6632 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6634 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6635 return cStatusSoftFailure;
6638 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6639 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6640 if ((!buffer) && (trace_pointer))
6642 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6643 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6644 if (!m_client_side_vertex_attrib_data[index].size())
6646 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6648 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6651 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribIPointer)
6652 GL_ENTRYPOINT(glVertexAttribIPointer)(index, size, type, stride, pPtr);
6654 GL_ENTRYPOINT(glVertexAttribIPointerEXT)(index, size, type, stride, pPtr);
6658 case VOGL_ENTRYPOINT_glVertexAttribPointerARB:
6659 case VOGL_ENTRYPOINT_glVertexAttribPointer:
6661 GLuint index = trace_packet.get_param_value<GLuint>(0);
6662 GLint size = trace_packet.get_param_value<GLint>(1);
6663 GLenum type = trace_packet.get_param_value<GLenum>(2);
6664 GLboolean normalized = trace_packet.get_param_value<GLboolean>(3);
6665 GLsizei stride = trace_packet.get_param_value<GLsizei>(4);
6666 vogl_trace_ptr_value trace_pointer = trace_packet.get_param_ptr_value(5);
6668 if (index >= m_pCur_context_state->m_context_info.get_max_vertex_attribs())
6670 process_entrypoint_error("%s: Generic vertex attribute index is too large\n", VOGL_METHOD_NAME);
6671 return cStatusSoftFailure;
6674 GLuint buffer = vogl_get_bound_gl_buffer(GL_ARRAY_BUFFER);
6675 void *pPtr = reinterpret_cast<void *>(trace_pointer);
6676 if ((!buffer) && (trace_pointer))
6678 // We've got a trace pointer to client side memory, but we don't have it until the actual draw.
6679 // So point this guy into one of our client size memory buffers that's hopefully large enough.
6680 if (!m_client_side_vertex_attrib_data[index].size())
6682 m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
6684 pPtr = m_client_side_vertex_attrib_data[index].get_ptr();
6687 if (entrypoint_id == VOGL_ENTRYPOINT_glVertexAttribPointer)
6688 GL_ENTRYPOINT(glVertexAttribPointer)(index, size, type, normalized, stride, pPtr);
6690 GL_ENTRYPOINT(glVertexAttribPointerARB)(index, size, type, normalized, stride, pPtr);
6694 case VOGL_ENTRYPOINT_glDrawRangeElements:
6695 case VOGL_ENTRYPOINT_glDrawRangeElementsEXT:
6697 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6698 GLuint start = trace_packet.get_param_value<GLuint>(1);
6699 GLuint end = trace_packet.get_param_value<GLuint>(2);
6700 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6701 GLenum type = trace_packet.get_param_value<GLenum>(4);
6702 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6704 const GLvoid *pIndices;
6705 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, 0, true, true))
6706 return cStatusSoftFailure;
6708 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6710 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawRangeElements)
6711 GL_ENTRYPOINT(glDrawRangeElements)(mode, start, end, count, type, pIndices);
6713 GL_ENTRYPOINT(glDrawRangeElementsEXT)(mode, start, end, count, type, pIndices);
6718 case VOGL_ENTRYPOINT_glDrawRangeElementsBaseVertex:
6720 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6721 GLuint start = trace_packet.get_param_value<GLuint>(1);
6722 GLuint end = trace_packet.get_param_value<GLuint>(2);
6723 GLsizei count = trace_packet.get_param_value<GLsizei>(3);
6724 GLenum type = trace_packet.get_param_value<GLenum>(4);
6725 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(5);
6726 GLint basevertex = trace_packet.get_param_value<GLint>(6);
6728 const GLvoid *pIndices;
6729 if (!draw_elements_client_side_array_setup(mode, start, end, count, type, trace_indices_ptr_value, pIndices, basevertex, true, true))
6730 return cStatusSoftFailure;
6732 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6734 GL_ENTRYPOINT(glDrawRangeElementsBaseVertex)(mode, start, end, count, type, pIndices, basevertex);
6739 case VOGL_ENTRYPOINT_glDrawElements:
6741 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6742 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6743 GLenum type = trace_packet.get_param_value<GLenum>(2);
6744 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6746 const GLvoid *pIndices;
6747 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6748 return cStatusSoftFailure;
6750 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6752 GL_ENTRYPOINT(glDrawElements)(mode, count, type, pIndices);
6757 case VOGL_ENTRYPOINT_glDrawArraysInstanced:
6758 case VOGL_ENTRYPOINT_glDrawArraysInstancedEXT:
6760 VOGL_REPLAY_LOAD_PARAMS_HELPER_glDrawArraysInstanced;
6762 const GLvoid *pIndices = NULL;
6763 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6764 return cStatusSoftFailure;
6766 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysInstancedEXT)
6768 GLsizei start = first, primcount = instancecount;
6769 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstancedEXT;
6772 VOGL_REPLAY_CALL_GL_HELPER_glDrawArraysInstanced;
6776 case VOGL_ENTRYPOINT_glDrawArrays:
6777 case VOGL_ENTRYPOINT_glDrawArraysEXT:
6779 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6780 GLint first = trace_packet.get_param_value<GLint>(1);
6781 GLsizei count = trace_packet.get_param_value<GLsizei>(2);
6783 const GLvoid *pIndices = NULL;
6784 if (!draw_elements_client_side_array_setup(mode, first, first + count - 1, count, GL_UNSIGNED_BYTE, 0, pIndices, 0, true, false))
6785 return cStatusSoftFailure;
6787 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6789 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawArraysEXT)
6790 GL_ENTRYPOINT(glDrawArraysEXT)(mode, first, count);
6792 GL_ENTRYPOINT(glDrawArrays)(mode, first, count);
6797 case VOGL_ENTRYPOINT_glDrawElementsInstanced:
6798 case VOGL_ENTRYPOINT_glDrawElementsInstancedARB:
6799 case VOGL_ENTRYPOINT_glDrawElementsInstancedEXT:
6801 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6802 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6803 GLenum type = trace_packet.get_param_value<GLenum>(2);
6804 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6805 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6807 const GLvoid *pIndices;
6808 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, 0, false, true))
6809 return cStatusSoftFailure;
6811 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6813 if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstanced)
6814 GL_ENTRYPOINT(glDrawElementsInstanced)(mode, count, type, pIndices, primcount);
6815 else if (entrypoint_id == VOGL_ENTRYPOINT_glDrawElementsInstancedEXT)
6816 GL_ENTRYPOINT(glDrawElementsInstancedEXT)(mode, count, type, pIndices, primcount);
6818 GL_ENTRYPOINT(glDrawElementsInstancedARB)(mode, count, type, pIndices, primcount);
6823 case VOGL_ENTRYPOINT_glDrawElementsInstancedBaseVertex:
6825 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6826 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6827 GLenum type = trace_packet.get_param_value<GLenum>(2);
6828 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6829 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6830 GLint basevertex = trace_packet.get_param_value<GLint>(5);
6832 const GLvoid *pIndices;
6833 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, basevertex, false, true))
6834 return cStatusSoftFailure;
6836 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6838 GL_ENTRYPOINT(glDrawElementsInstancedBaseVertex)(mode, count, type, pIndices, primcount, basevertex);
6843 case VOGL_ENTRYPOINT_glMultiDrawArrays:
6844 case VOGL_ENTRYPOINT_glMultiDrawArraysEXT:
6846 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6848 const GLint *pFirst = trace_packet.get_param_client_memory<const GLint>(1);
6849 uint first_size = trace_packet.get_param_client_memory_data_size(1);
6851 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(2);
6852 uint count_size = trace_packet.get_param_client_memory_data_size(2);
6854 GLsizei primcount = trace_packet.get_param_value<GLsizei>(3);
6856 if ((first_size != primcount * sizeof(GLint)) || (count_size != primcount * sizeof(GLsizei)))
6858 process_entrypoint_error("%s: first and/or count params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6859 return cStatusSoftFailure;
6862 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6864 // Multi-draws with client side arrays are not supported for replay.
6865 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6866 GL_ENTRYPOINT(glMultiDrawArrays)(mode, pFirst, pCount, primcount);
6868 GL_ENTRYPOINT(glMultiDrawArraysEXT)(mode, pFirst, pCount, primcount);
6873 case VOGL_ENTRYPOINT_glMultiDrawElements:
6874 case VOGL_ENTRYPOINT_glMultiDrawElementsEXT:
6876 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6878 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6879 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6881 GLenum type = trace_packet.get_param_value<GLenum>(2);
6883 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6885 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6887 if ((count_size != static_cast<uint>(primcount * sizeof(GLsizei))) || (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)))
6889 process_entrypoint_error("%s: count and/or indices params do not point to arrays of the expected size\n", VOGL_METHOD_NAME);
6890 return cStatusSoftFailure;
6893 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6894 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6895 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6897 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6899 // Multi-draws with client side arrays are not supported for replay.
6900 if (entrypoint_id == VOGL_ENTRYPOINT_glMultiDrawElements)
6901 GL_ENTRYPOINT(glMultiDrawElements)(mode, pCount, type, replay_indices.get_ptr(), primcount);
6903 GL_ENTRYPOINT(glMultiDrawElementsEXT)(mode, pCount, type, (const GLvoid **)replay_indices.get_ptr(), primcount);
6908 case VOGL_ENTRYPOINT_glMultiDrawElementsBaseVertex:
6910 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6912 const GLsizei *pCount = trace_packet.get_param_client_memory<const GLsizei>(1);
6913 uint count_size = trace_packet.get_param_client_memory_data_size(1);
6915 GLenum type = trace_packet.get_param_value<GLenum>(2);
6917 const vogl_client_memory_array trace_indices_void_ptr_array = trace_packet.get_param_client_memory_array(3); // const GLvoid *
6918 //GLvoid * const *ppIndices = trace_packet.get_param_client_memory<GLvoid *>(3);
6919 //uint index_size = trace_packet.get_param_client_memory_data_size(3);
6921 GLsizei primcount = trace_packet.get_param_value<GLsizei>(4);
6923 const GLint *pBase_vertex = trace_packet.get_param_client_memory<const GLint>(5);
6924 uint base_vertex_size = trace_packet.get_param_client_memory_data_size(5);
6926 if ((count_size != primcount * sizeof(GLsizei)) ||
6927 (trace_indices_void_ptr_array.size() != static_cast<uint>(primcount)) ||
6928 (base_vertex_size != primcount * sizeof(GLint)))
6930 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);
6931 return cStatusSoftFailure;
6934 vogl::growable_array<GLvoid *, 256> replay_indices(trace_indices_void_ptr_array.size());
6935 for (uint i = 0; i < trace_indices_void_ptr_array.size(); i++)
6936 replay_indices[i] = reinterpret_cast<GLvoid *>(trace_indices_void_ptr_array.get_element<vogl_trace_ptr_value>(i));
6938 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6940 // Multi-draws with client side arrays are not supported for replay.
6941 GL_ENTRYPOINT(glMultiDrawElementsBaseVertex)(mode, pCount, type, replay_indices.get_ptr(), primcount, pBase_vertex);
6946 case VOGL_ENTRYPOINT_glDrawElementsBaseVertex:
6948 GLenum mode = trace_packet.get_param_value<GLenum>(0);
6949 GLsizei count = trace_packet.get_param_value<GLsizei>(1);
6950 GLenum type = trace_packet.get_param_value<GLenum>(2);
6951 vogl_trace_ptr_value trace_indices_ptr_value = trace_packet.get_param_ptr_value(3);
6952 GLint base_vertex = trace_packet.get_param_value<GLint>(4);
6954 const GLvoid *pIndices;
6955 if (!draw_elements_client_side_array_setup(mode, 0, 0, count, type, trace_indices_ptr_value, pIndices, base_vertex, false, true))
6956 return cStatusSoftFailure;
6958 if (m_frame_draw_counter < m_frame_draw_counter_kill_threshold)
6960 GL_ENTRYPOINT(glDrawElementsBaseVertex)(mode, count, type, pIndices, base_vertex);
6965 case VOGL_ENTRYPOINT_glGetBufferSubData:
6967 if (!benchmark_mode())
6969 GLenum target = trace_packet.get_param_value<GLenum>(0);
6970 vogl_trace_ptr_value offset = trace_packet.get_param_ptr_value(1);
6971 vogl_trace_ptr_value size = trace_packet.get_param_ptr_value(2);
6972 GLvoid *pTrace_ptr = trace_packet.get_param_client_memory<GLvoid>(3);
6974 if (offset != static_cast<uintptr_t>(offset))
6976 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)offset);
6977 return cStatusHardFailure;
6980 if ((size > cUINT32_MAX) || (size != static_cast<uintptr_t>(size)))
6982 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, (uint64_t)size);
6983 return cStatusHardFailure;
6986 vogl::growable_array<uint8, 1024> buf(pTrace_ptr ? static_cast<uint>(size) : 0);
6988 GL_ENTRYPOINT(glGetBufferSubData)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), pTrace_ptr ? buf.get_ptr() : NULL);
6990 if ((buf.size()) && (pTrace_ptr))
6992 if (memcmp(buf.get_ptr(), pTrace_ptr, static_cast<size_t>(size)) != 0)
6994 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7001 case VOGL_ENTRYPOINT_glGetClipPlane:
7003 if (!benchmark_mode())
7005 GLenum plane = trace_packet.get_param_value<GLenum>(0);
7006 const GLdouble *pTrace_equation = trace_packet.get_param_client_memory<GLdouble>(1);
7008 GLdouble equation[4];
7009 GL_ENTRYPOINT(glGetClipPlane)(plane, pTrace_equation ? equation : NULL);
7011 if (pTrace_equation)
7013 if (memcmp(equation, pTrace_equation, sizeof(GLdouble) * 4) != 0)
7015 process_entrypoint_warning("%s: Replay's returned data differed from trace's\n", VOGL_METHOD_NAME);
7022 case VOGL_ENTRYPOINT_glBufferData:
7023 case VOGL_ENTRYPOINT_glBufferDataARB:
7025 GLenum target = trace_packet.get_param_value<GLenum>(0);
7026 vogl_trace_ptr_value size = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLsizeiptrARB
7027 const GLvoid *data = trace_packet.get_param_client_memory_ptr(2);
7028 uint data_size = trace_packet.get_param_client_memory_data_size(2);
7029 GLenum usage = trace_packet.get_param_value<GLenum>(3);
7031 if ((data) && (static_cast<vogl_trace_ptr_value>(data_size) < size))
7033 process_entrypoint_error("%s: trace's data array is too small\n", VOGL_METHOD_NAME);
7034 return cStatusHardFailure;
7037 if (size != static_cast<uintptr_t>(size))
7039 process_entrypoint_error("%s: size parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(size));
7040 return cStatusHardFailure;
7043 if (entrypoint_id == VOGL_ENTRYPOINT_glBufferData)
7044 g_vogl_actual_gl_entrypoints.m_glBufferData(target, static_cast<GLsizeiptr>(size), data, usage);
7046 g_vogl_actual_gl_entrypoints.m_glBufferDataARB(target, static_cast<GLsizeiptrARB>(size), data, usage);
7048 GLuint buffer = vogl_get_bound_gl_buffer(target);
7052 for (i = 0; i < get_shared_state()->m_mapped_buffers.size(); i++)
7054 if (get_shared_state()->m_mapped_buffers[i].m_buffer == buffer)
7056 process_entrypoint_warning("%s: glBufferData() called on already mapped GL buffer %u, assuming GL will be unmapping it\n", VOGL_METHOD_NAME, buffer);
7058 get_shared_state()->m_mapped_buffers.erase_unordered(i);
7066 case VOGL_ENTRYPOINT_glMapBufferARB:
7067 case VOGL_ENTRYPOINT_glMapBuffer:
7069 GLenum target = trace_packet.get_param_value<GLenum>(0);
7070 GLenum access = trace_packet.get_param_value<GLenum>(1);
7071 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7073 // FIXME - must call GL even if !pTrace_result
7074 if (trace_result_ptr_value)
7077 if (entrypoint_id == VOGL_ENTRYPOINT_glMapBuffer)
7078 pMap = GL_ENTRYPOINT(glMapBuffer)(target, access);
7080 pMap = GL_ENTRYPOINT(glMapBufferARB)(target, access);
7084 process_entrypoint_error("%s: glMapBuffer succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7085 return cStatusHardFailure;
7088 GLuint buffer = vogl_get_bound_gl_buffer(target);
7091 for (i = 0; i < get_shared_state()->m_mapped_buffers.size(); i++)
7093 if (get_shared_state()->m_mapped_buffers[i].m_buffer == buffer)
7095 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7096 return cStatusHardFailure;
7100 if (i == get_shared_state()->m_mapped_buffers.size())
7103 GL_ENTRYPOINT(glGetBufferParameteriv)(target, GL_BUFFER_SIZE, &length);
7105 mapped_buffer_desc m;
7106 m.m_buffer = buffer;
7107 m.m_target = target;
7109 m.m_length = length;
7110 m.m_access = access;
7113 get_shared_state()->m_mapped_buffers.push_back(m);
7119 case VOGL_ENTRYPOINT_glMapBufferRange:
7121 GLenum target = trace_packet.get_param_value<GLenum>(0);
7122 vogl_trace_ptr_value offset = trace_packet.get_param_value<vogl_trace_ptr_value>(1); // GLintptr
7123 vogl_trace_ptr_value length = trace_packet.get_param_value<vogl_trace_ptr_value>(2); // GLsizeiptr
7124 GLbitfield access = trace_packet.get_param_value<GLbitfield>(3);
7125 vogl_trace_ptr_value trace_result_ptr_value = trace_packet.get_return_ptr_value();
7127 if (offset != static_cast<uintptr_t>(offset))
7129 process_entrypoint_error("%s: offset parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(offset));
7130 return cStatusHardFailure;
7132 if (length != static_cast<uintptr_t>(length))
7134 process_entrypoint_error("%s: length parameter is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(length));
7135 return cStatusHardFailure;
7138 // FIXME - must call GL even if !pTrace_result
7139 if (trace_result_ptr_value)
7141 void *pMap = GL_ENTRYPOINT(glMapBufferRange)(target, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(length), access);
7144 process_entrypoint_error("%s: glMapBufferRange succeeded during trace, but failed during replay!\n", VOGL_METHOD_NAME);
7145 return cStatusHardFailure;
7148 GLuint buffer = vogl_get_bound_gl_buffer(target);
7150 for (i = 0; i < get_shared_state()->m_mapped_buffers.size(); i++)
7152 if (get_shared_state()->m_mapped_buffers[i].m_buffer == buffer)
7154 process_entrypoint_error("%s: Buffer %u is already mapped\n", VOGL_METHOD_NAME, buffer);
7155 return cStatusHardFailure;
7159 if (i == get_shared_state()->m_mapped_buffers.size())
7161 mapped_buffer_desc m;
7162 m.m_buffer = buffer;
7163 m.m_target = target;
7164 m.m_offset = offset;
7165 m.m_length = length;
7166 m.m_access = access;
7169 get_shared_state()->m_mapped_buffers.push_back(m);
7175 case VOGL_ENTRYPOINT_glFlushMappedBufferRange:
7177 // vogltrace queues up the flushes, will process them while handling the glUnmapBuffer() call
7180 case VOGL_ENTRYPOINT_glUnmapBufferARB:
7181 case VOGL_ENTRYPOINT_glUnmapBuffer:
7183 GLenum target = trace_packet.get_param_value<GLenum>(0);
7184 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7186 GLuint buffer = vogl_get_bound_gl_buffer(target);
7188 // FIXME - must call GL even if !buffer
7191 uint mapped_buffers_index;
7192 for (mapped_buffers_index = 0; mapped_buffers_index < get_shared_state()->m_mapped_buffers.size(); mapped_buffers_index++)
7193 if (get_shared_state()->m_mapped_buffers[mapped_buffers_index].m_buffer == buffer)
7195 if (mapped_buffers_index == get_shared_state()->m_mapped_buffers.size())
7197 process_entrypoint_error("%s: Unable to find mapped buffer during unmap\n", VOGL_METHOD_NAME);
7198 return cStatusHardFailure;
7201 mapped_buffer_desc &map_desc = get_shared_state()->m_mapped_buffers[mapped_buffers_index];
7203 bool writable_map = false;
7204 bool explicit_bit = false;
7205 if (map_desc.m_range)
7207 writable_map = ((map_desc.m_access & GL_MAP_WRITE_BIT) != 0);
7208 explicit_bit = (map_desc.m_access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0;
7212 writable_map = (map_desc.m_access != GL_READ_ONLY);
7217 const key_value_map &unmap_data = trace_packet.get_key_value_map();
7221 int num_flushed_ranges = unmap_data.get_int(string_hash("flushed_ranges"));
7223 for (int i = 0; i < num_flushed_ranges; i++)
7225 int64_t ofs = unmap_data.get_int64(i * 4 + 0);
7226 int64_t size = unmap_data.get_int64(i * 4 + 1);
7227 VOGL_NOTE_UNUSED(size);
7228 const uint8_vec *pData = unmap_data.get_blob(i * 4 + 2);
7231 process_entrypoint_error("%s: Failed finding flushed range data in key value map\n", VOGL_METHOD_NAME);
7232 return cStatusHardFailure;
7235 if (ofs != static_cast<GLintptr>(ofs))
7237 process_entrypoint_error("%s: Flush offset is too large (%" PRIu64 ")\n", VOGL_METHOD_NAME, static_cast<uint64_t>(ofs));
7238 return cStatusHardFailure;
7241 VOGL_ASSERT(size == pData->size());
7243 memcpy(static_cast<uint8 *>(map_desc.m_pPtr) + ofs, pData->get_ptr(), pData->size());
7245 GL_ENTRYPOINT(glFlushMappedBufferRange)(target, static_cast<GLintptr>(ofs), pData->size());
7250 int64_t ofs = unmap_data.get_int64(0);
7251 VOGL_NOTE_UNUSED(ofs);
7252 int64_t size = unmap_data.get_int64(1);
7253 VOGL_NOTE_UNUSED(size);
7254 const uint8_vec *pData = unmap_data.get_blob(2);
7257 process_entrypoint_error("%s: Failed finding mapped data in key value map\n", VOGL_METHOD_NAME);
7258 return cStatusHardFailure;
7262 memcpy(map_desc.m_pPtr, pData->get_ptr(), pData->size());
7267 get_shared_state()->m_mapped_buffers.erase_unordered(mapped_buffers_index);
7270 GLboolean replay_result;
7271 if (entrypoint_id == VOGL_ENTRYPOINT_glUnmapBuffer)
7272 replay_result = GL_ENTRYPOINT(glUnmapBuffer)(target);
7274 replay_result = GL_ENTRYPOINT(glUnmapBufferARB)(target);
7276 if (trace_result != replay_result)
7277 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);
7281 case VOGL_ENTRYPOINT_glGenVertexArrays:
7283 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))
7284 return cStatusHardFailure;
7287 case VOGL_ENTRYPOINT_glBindVertexArray:
7289 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7290 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7292 GL_ENTRYPOINT(glBindVertexArray)(replay_handle);
7295 case VOGL_ENTRYPOINT_glDeleteVertexArrays:
7297 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));
7300 case VOGL_ENTRYPOINT_glIsFramebuffer:
7301 case VOGL_ENTRYPOINT_glIsFramebufferEXT:
7303 if (!benchmark_mode())
7305 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7306 GLuint replay_handle = map_handle(get_context_state()->m_framebuffers, trace_handle);
7307 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7309 GLboolean replay_result;
7310 if (entrypoint_id == VOGL_ENTRYPOINT_glIsFramebuffer)
7311 replay_result = GL_ENTRYPOINT(glIsFramebuffer)(replay_handle);
7313 replay_result = GL_ENTRYPOINT(glIsFramebufferEXT)(replay_handle);
7315 if (trace_result != replay_result)
7316 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));
7321 case VOGL_ENTRYPOINT_glIsBuffer:
7323 if (!benchmark_mode())
7325 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7326 GLuint replay_handle = map_handle(get_shared_state()->m_buffers, trace_handle);
7327 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7329 GLboolean replay_result = GL_ENTRYPOINT(glIsBuffer)(replay_handle);
7330 if (trace_result != replay_result)
7331 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));
7335 case VOGL_ENTRYPOINT_glIsEnabledi:
7337 if (!benchmark_mode())
7339 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7340 GLuint index = trace_packet.get_param_value<GLuint>(1);
7341 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7343 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabledi)(cap, index);
7344 if (trace_result != replay_result)
7345 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));
7349 case VOGL_ENTRYPOINT_glIsEnabled:
7351 if (!benchmark_mode())
7353 GLenum cap = trace_packet.get_param_value<GLenum>(0);
7354 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7356 GLboolean replay_result = GL_ENTRYPOINT(glIsEnabled)(cap);
7357 if (trace_result != replay_result)
7358 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));
7362 case VOGL_ENTRYPOINT_glIsProgram:
7364 if (!benchmark_mode())
7366 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7367 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7368 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7370 GLboolean replay_result = GL_ENTRYPOINT(glIsProgram)(replay_handle);
7372 if (trace_result != replay_result)
7373 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));
7377 case VOGL_ENTRYPOINT_glIsQuery:
7379 if (!benchmark_mode())
7381 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7382 GLuint replay_handle = map_handle(get_shared_state()->m_queries, trace_handle);
7383 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7385 GLboolean replay_result = GL_ENTRYPOINT(glIsQuery)(replay_handle);
7386 if (trace_result != replay_result)
7387 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));
7391 case VOGL_ENTRYPOINT_glIsShader:
7393 if (!benchmark_mode())
7395 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7396 GLuint replay_handle = map_handle(get_shared_state()->m_shadow_state.m_objs, trace_handle);
7397 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7399 GLboolean replay_result = GL_ENTRYPOINT(glIsShader)(replay_handle);
7400 if (trace_result != replay_result)
7401 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));
7405 case VOGL_ENTRYPOINT_glIsTexture:
7406 case VOGL_ENTRYPOINT_glIsTextureEXT:
7408 if (!benchmark_mode())
7410 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7411 GLuint replay_handle = trace_handle;
7412 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7414 map_handle(get_shared_state()->m_shadow_state.m_textures, trace_handle, replay_handle);
7416 GLboolean replay_result;
7417 if (entrypoint_id == VOGL_ENTRYPOINT_glIsTexture)
7418 replay_result = GL_ENTRYPOINT(glIsTexture)(replay_handle);
7420 replay_result = GL_ENTRYPOINT(glIsTextureEXT)(replay_handle);
7422 if (trace_result != replay_result)
7423 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));
7428 case VOGL_ENTRYPOINT_glIsVertexArray:
7430 if (!benchmark_mode())
7432 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7433 GLuint replay_handle = map_handle(get_context_state()->m_vertex_array_objects, trace_handle);
7434 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7436 GLboolean replay_result = GL_ENTRYPOINT(glIsVertexArray)(replay_handle);
7437 if (trace_result != replay_result)
7438 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));
7443 case VOGL_ENTRYPOINT_glReadPixels:
7445 // TODO: This is causing huge stalls when replaying metro, not sure why. Also, the # of traced bytes is zero in metro.
7447 if (!benchmark_mode())
7449 GLint x = trace_packet.get_param_value<GLint>(0);
7450 GLint y = trace_packet.get_param_value<GLint>(1);
7451 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7452 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7453 GLenum format = trace_packet.get_param_value<GLenum>(4);
7454 GLenum type = trace_packet.get_param_value<GLenum>(5);
7455 const GLvoid *trace_data = trace_packet.get_param_client_memory<const GLvoid>(6);
7456 uint trace_data_size = trace_packet.get_param_client_memory_data_size(6);
7458 size_t replay_data_size = vogl_get_image_size(format, type, width, height, 1);
7459 if (replay_data_size != trace_data_size)
7461 process_entrypoint_warning("%s: Unexpected trace data size, got %u expected %" PRIu64 "\n", VOGL_METHOD_NAME, trace_data_size, (uint64_t)replay_data_size);
7463 else if (!trace_data)
7465 process_entrypoint_warning("%s: Trace data is missing from packet\n", VOGL_METHOD_NAME);
7468 if (replay_data_size > cUINT32_MAX)
7470 process_entrypoint_error("%s: Replay data size is too large (%" PRIu64 ")!\n", VOGL_METHOD_NAME, (uint64_t)replay_data_size);
7471 return cStatusHardFailure;
7474 vogl::vector<uint8> data(static_cast<uint>(replay_data_size));
7475 GL_ENTRYPOINT(glReadPixels)(x, y, width, height, format, type, data.get_ptr());
7477 if ((trace_data_size == replay_data_size) && (trace_data_size) && (trace_data))
7479 if (memcmp(data.get_ptr(), trace_data, trace_data_size) != 0)
7481 process_entrypoint_error("%s: Replay's returned pixel data differed from trace's!\n", VOGL_METHOD_NAME);
7488 case VOGL_ENTRYPOINT_glGetTexLevelParameterfv:
7490 if (!benchmark_mode())
7492 GLenum target = trace_packet.get_param_value<GLenum>(0);
7493 GLint level = trace_packet.get_param_value<GLint>(1);
7494 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7495 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(3);
7496 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7498 int n = g_gl_enums.get_pname_count(pname);
7501 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7502 return cStatusSoftFailure;
7505 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7506 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7508 GL_ENTRYPOINT(glGetTexLevelParameterfv)(target, level, pname, replay_params.get_ptr());
7510 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7513 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7514 else if (trace_params_size != sizeof(GLfloat) * n)
7515 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7516 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7517 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7522 case VOGL_ENTRYPOINT_glGetTexLevelParameteriv:
7524 if (!benchmark_mode())
7526 GLenum target = trace_packet.get_param_value<GLenum>(0);
7527 GLint level = trace_packet.get_param_value<GLint>(1);
7528 GLenum pname = trace_packet.get_param_value<GLenum>(2);
7529 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(3);
7530 uint trace_params_size = trace_packet.get_param_client_memory_data_size(3);
7532 int n = g_gl_enums.get_pname_count(pname);
7535 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7536 return cStatusSoftFailure;
7539 vogl::growable_array<GLint, 16> replay_params(n + 1);
7540 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7542 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, level, pname, replay_params.get_ptr());
7544 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7547 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7548 else if (trace_params_size != sizeof(GLint) * n)
7549 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7550 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7551 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7556 case VOGL_ENTRYPOINT_glGetTexParameterIiv:
7557 case VOGL_ENTRYPOINT_glGetTexParameteriv:
7559 if (!benchmark_mode())
7561 GLenum target = trace_packet.get_param_value<GLenum>(0);
7562 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7563 const GLint *pTrace_params = trace_packet.get_param_client_memory<const GLint>(2);
7564 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7566 int n = g_gl_enums.get_pname_count(pname);
7569 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7570 return cStatusSoftFailure;
7573 vogl::growable_array<GLint, 16> replay_params(n + 1);
7574 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7576 if (entrypoint_id == VOGL_ENTRYPOINT_glGetTexParameterIiv)
7577 GL_ENTRYPOINT(glGetTexParameterIiv)(target, pname, replay_params.get_ptr());
7579 GL_ENTRYPOINT(glGetTexParameteriv)(target, pname, replay_params.get_ptr());
7581 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7584 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7585 else if (trace_params_size != sizeof(GLint) * n)
7586 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7587 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLint) * n) != 0)
7588 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7593 case VOGL_ENTRYPOINT_glGetTexParameterIuiv:
7595 if (!benchmark_mode())
7597 GLenum target = trace_packet.get_param_value<GLenum>(0);
7598 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7599 const GLuint *pTrace_params = trace_packet.get_param_client_memory<const GLuint>(2);
7600 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7602 int n = g_gl_enums.get_pname_count(pname);
7605 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7606 return cStatusSoftFailure;
7609 vogl::growable_array<GLuint, 16> replay_params(n + 1);
7610 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC;
7612 GL_ENTRYPOINT(glGetTexParameterIuiv)(target, pname, replay_params.get_ptr());
7614 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_INT_MAGIC);
7617 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7618 else if (trace_params_size != sizeof(GLuint) * n)
7619 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7620 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLuint) * n) != 0)
7621 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7626 case VOGL_ENTRYPOINT_glGetTexParameterfv:
7628 if (!benchmark_mode())
7630 GLenum target = trace_packet.get_param_value<GLenum>(0);
7631 GLenum pname = trace_packet.get_param_value<GLenum>(1);
7632 const GLfloat *pTrace_params = trace_packet.get_param_client_memory<const GLfloat>(2);
7633 uint trace_params_size = trace_packet.get_param_client_memory_data_size(2);
7635 int n = g_gl_enums.get_pname_count(pname);
7638 process_entrypoint_error("%s: Can't determine count of GL pname 0x%08X\n", VOGL_METHOD_NAME, pname);
7639 return cStatusSoftFailure;
7642 vogl::growable_array<GLfloat, 17> replay_params(n + 1);
7643 replay_params[n] = VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC;
7645 GL_ENTRYPOINT(glGetTexParameterfv)(target, pname, replay_params.get_ptr());
7647 VOGL_VERIFY(replay_params[n] == VOGL_GL_REPLAYER_ARRAY_OVERRUN_FLOAT_MAGIC);
7650 process_entrypoint_warning("%s: Trace param data is missing from packet\n", VOGL_METHOD_NAME);
7651 else if (trace_params_size != sizeof(GLfloat) * n)
7652 process_entrypoint_warning("%s: Invalid trace param data size\n", VOGL_METHOD_NAME);
7653 else if (memcmp(pTrace_params, replay_params.get_ptr(), sizeof(GLfloat) * n) != 0)
7654 process_entrypoint_error("%s: Trace's param data differs from replay's\n", VOGL_METHOD_NAME);
7660 case VOGL_ENTRYPOINT_glGetVertexAttribdv:
7662 status = get_vertex_attrib_helper<GLdouble>(GL_ENTRYPOINT(glGetVertexAttribdv));
7663 if (status != cStatusOK)
7667 case VOGL_ENTRYPOINT_glGetVertexAttribfv:
7669 status = get_vertex_attrib_helper<GLfloat>(GL_ENTRYPOINT(glGetVertexAttribfv));
7670 if (status != cStatusOK)
7674 case VOGL_ENTRYPOINT_glGetVertexAttribiv:
7676 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribiv));
7677 if (status != cStatusOK)
7681 case VOGL_ENTRYPOINT_glGetVertexAttribIiv:
7683 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIiv));
7684 if (status != cStatusOK)
7688 case VOGL_ENTRYPOINT_glGetVertexAttribIivEXT:
7690 status = get_vertex_attrib_helper<GLint>(GL_ENTRYPOINT(glGetVertexAttribIivEXT));
7691 if (status != cStatusOK)
7695 case VOGL_ENTRYPOINT_glGetVertexAttribIuiv:
7697 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuiv));
7698 if (status != cStatusOK)
7702 case VOGL_ENTRYPOINT_glGetVertexAttribIuivEXT:
7704 status = get_vertex_attrib_helper<GLuint>(GL_ENTRYPOINT(glGetVertexAttribIuivEXT));
7705 if (status != cStatusOK)
7709 case VOGL_ENTRYPOINT_glGenLists:
7711 GLsizei range = trace_packet.get_param_value<GLsizei>(0);
7712 GLuint trace_base_handle = trace_packet.get_return_value<GLuint>();
7714 if (trace_base_handle)
7718 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7720 if ((check_gl_error()) || (!replay_base_handle))
7722 process_entrypoint_error("%s: glGenLists() succeeded in the trace, but failed during replay!\n", VOGL_METHOD_NAME);
7723 return cStatusHardFailure;
7726 for (GLsizei i = 0; i < range; i++)
7728 GLuint trace_handle = trace_base_handle + i;
7729 GLuint replay_handle = replay_base_handle + i;
7731 if (!gen_handle(get_shared_state()->m_lists, trace_handle, replay_handle))
7732 return cStatusHardFailure;
7734 if (!get_shared_state()->m_shadow_state.m_display_lists.gen_lists(trace_handle, 1, &replay_handle))
7736 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);
7742 GLuint replay_base_handle = GL_ENTRYPOINT(glGenLists)(range);
7743 if (replay_base_handle)
7745 process_entrypoint_warning("%s: glGenLists() failed in the trace, but succeeded during replay!\n", VOGL_METHOD_NAME);
7747 GL_ENTRYPOINT(glDeleteLists)(replay_base_handle, range);
7753 case VOGL_ENTRYPOINT_glCallList:
7755 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7756 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7758 GL_ENTRYPOINT(glCallList)(replay_handle);
7760 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7762 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7765 if ((status = post_draw_call()) != cStatusOK)
7770 case VOGL_ENTRYPOINT_glCallLists:
7772 GLsizei n = trace_packet.get_param_value<GLsizei>(0);
7773 GLenum type = trace_packet.get_param_value<GLenum>(1);
7774 const GLvoid *pTrace_lists = trace_packet.get_param_client_memory<const GLvoid>(2);
7775 uint trace_lists_size = trace_packet.get_param_client_memory_data_size(2);
7777 uint type_size = vogl_get_gl_type_size(type);
7780 process_entrypoint_error("%s: Unable to execute glCallLists, type is invalid\n", VOGL_METHOD_NAME);
7781 return cStatusSoftFailure;
7784 if ((n) && (!pTrace_lists))
7786 process_entrypoint_error("%s: Unable to execute glCallLists, lists param is NULL\n", VOGL_METHOD_NAME);
7787 return cStatusSoftFailure;
7790 if (trace_lists_size < (type_size * n))
7792 process_entrypoint_error("%s: Unable to execute glCallLists, lists param data size is too small in trace\n", VOGL_METHOD_NAME);
7793 return cStatusSoftFailure;
7796 GLuint list_base = 0;
7797 GL_ENTRYPOINT(glGetIntegerv)(GL_LIST_BASE, reinterpret_cast<GLint *>(&list_base));
7799 const uint8 *pTrace_lists_ptr = static_cast<const uint8 *>(pTrace_lists);
7800 for (GLsizei i = 0; i < n; i++)
7802 GLint trace_handle = list_base;
7807 trace_handle += *reinterpret_cast<const signed char *>(pTrace_lists_ptr);
7811 case GL_UNSIGNED_BYTE:
7813 trace_handle += *pTrace_lists_ptr;
7819 trace_handle += *reinterpret_cast<const int16 *>(pTrace_lists_ptr);
7820 pTrace_lists_ptr += sizeof(int16);
7823 case GL_UNSIGNED_SHORT:
7825 trace_handle += *reinterpret_cast<const uint16 *>(pTrace_lists_ptr);
7826 pTrace_lists_ptr += sizeof(uint16);
7831 trace_handle += *reinterpret_cast<const int32 *>(pTrace_lists_ptr);
7832 pTrace_lists_ptr += sizeof(int32);
7835 case GL_UNSIGNED_INT:
7837 trace_handle += *reinterpret_cast<const uint32 *>(pTrace_lists_ptr);
7838 pTrace_lists_ptr += sizeof(uint32);
7843 trace_handle += static_cast<GLint>(*reinterpret_cast<const float *>(pTrace_lists_ptr));
7844 pTrace_lists_ptr += sizeof(float);
7849 trace_handle += ((pTrace_lists_ptr[0] << 8U) + pTrace_lists_ptr[1]);
7850 pTrace_lists_ptr += 2;
7855 trace_handle += ((pTrace_lists_ptr[0] << 16U) + (pTrace_lists_ptr[1] << 8U) + pTrace_lists_ptr[2]);
7856 pTrace_lists_ptr += 3;
7861 trace_handle += ((pTrace_lists_ptr[0] << 24U) + (pTrace_lists_ptr[1] << 16U) + (pTrace_lists_ptr[2] << 8U) + pTrace_lists_ptr[3]);
7862 pTrace_lists_ptr += 4;
7867 process_entrypoint_error("%s: Invalid type parameter (0x%08X)\n", VOGL_METHOD_NAME, type);
7868 return cStatusSoftFailure;
7872 if (trace_handle <= 0)
7874 process_entrypoint_error("%s: Trace handle after adding list base is negative (%i), skipping this list index\n", VOGL_METHOD_NAME, trace_handle);
7878 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7879 GL_ENTRYPOINT(glCallList)(replay_handle);
7881 if (!get_shared_state()->m_shadow_state.m_display_lists.parse_list_and_update_shadows(trace_handle, display_list_bind_callback, this))
7883 process_entrypoint_warning("%s: Failed processing display list shadow for trace handle %u GL handle %u\n", VOGL_METHOD_NAME, trace_handle, replay_handle);
7888 if ((status = post_draw_call()) != cStatusOK)
7893 case VOGL_ENTRYPOINT_glDeleteLists:
7895 GLuint trace_list = trace_packet.get_param_value<GLuint>(0);
7896 GLsizei range = trace_packet.get_param_value<GLsizei>(1);
7898 for (GLsizei i = 0; i < range; i++)
7900 GLuint trace_handle = trace_list + i;
7901 delete_handles(get_shared_state()->m_lists, 1, &trace_handle, delete_list_helper);
7903 if (!get_shared_state()->m_shadow_state.m_display_lists.del_lists(trace_handle, 1))
7905 process_entrypoint_warning("%s: Unable to delete list in display list shadow, trace handle %u\n", VOGL_METHOD_NAME, trace_handle);
7911 case VOGL_ENTRYPOINT_glIsList:
7913 if (!benchmark_mode())
7915 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7916 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7917 GLboolean trace_result = trace_packet.get_return_value<GLboolean>();
7919 GLboolean replay_result = GL_ENTRYPOINT(glIsList)(replay_handle);
7920 if (trace_result != replay_result)
7921 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));
7926 case VOGL_ENTRYPOINT_glNewList:
7928 GLuint trace_handle = trace_packet.get_param_value<GLuint>(0);
7929 GLuint replay_handle = map_handle(get_shared_state()->m_lists, trace_handle);
7930 GLenum mode = trace_packet.get_param_value<GLenum>(1);
7934 GL_ENTRYPOINT(glNewList)(replay_handle, mode);
7936 if (!check_gl_error())
7938 get_shared_state()->m_shadow_state.m_display_lists.new_list(trace_handle, replay_handle);
7940 get_context_state()->m_current_display_list_mode = mode;
7941 get_context_state()->m_current_display_list_handle = trace_handle;
7944 // TODO: Check if glNewList() failed vs the replay.
7945 // This is important, because if the new failed during tracing but succeeded during replay then we've seriously diverged.
7946 // 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.
7949 case VOGL_ENTRYPOINT_glListBase:
7951 GLuint base = trace_packet.get_param_value<GLuint>(0);
7952 GL_ENTRYPOINT(glListBase)(base);
7955 case VOGL_ENTRYPOINT_glEndList:
7957 GL_ENTRYPOINT(glEndList)();
7959 if (!get_context_state()->is_composing_display_list())
7961 process_entrypoint_warning("%s: glEndList() called without calling glNewList()!\n", VOGL_METHOD_NAME);
7965 if (!get_shared_state()->m_shadow_state.m_display_lists.end_list(get_context_state()->m_current_display_list_handle))
7966 process_entrypoint_warning("%s: Failed ending display list, trace handle %u\n", VOGL_METHOD_NAME, get_context_state()->m_current_display_list_handle);
7968 get_context_state()->m_current_display_list_mode = GL_NONE;
7969 get_context_state()->m_current_display_list_handle = -1;
7974 case VOGL_ENTRYPOINT_glFeedbackBuffer:
7976 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
7977 GLenum type = trace_packet.get_param_value<GLenum>(1);
7979 if (static_cast<GLsizei>(m_pCur_context_state->m_feedback_buffer.size()) < size)
7980 m_pCur_context_state->m_feedback_buffer.resize(size);
7982 GL_ENTRYPOINT(glFeedbackBuffer)(size, type, m_pCur_context_state->m_feedback_buffer.get_ptr());
7986 case VOGL_ENTRYPOINT_glSeparableFilter2D:
7988 GLenum target = trace_packet.get_param_value<GLenum>(0);
7989 GLenum internalformat = trace_packet.get_param_value<GLenum>(1);
7990 GLsizei width = trace_packet.get_param_value<GLsizei>(2);
7991 GLsizei height = trace_packet.get_param_value<GLsizei>(3);
7992 GLenum format = trace_packet.get_param_value<GLenum>(4);
7993 GLenum type = trace_packet.get_param_value<GLenum>(5);
7995 const GLvoid *row = trace_packet.get_param_client_memory<const GLvoid>(6);
7996 uint row_size = trace_packet.get_param_client_memory_data_size(6);
7997 if (row_size < vogl_get_image_size(format, type, width, 1, 1))
7999 process_entrypoint_error("%s: row trace array is too small\n", VOGL_METHOD_NAME);
8000 return cStatusSoftFailure;
8003 const GLvoid *column = trace_packet.get_param_client_memory<const GLvoid>(7);
8004 uint col_size = trace_packet.get_param_client_memory_data_size(7);
8005 if (col_size < vogl_get_image_size(format, type, width, 1, 1))
8007 process_entrypoint_error("%s: column trace array is too small\n", VOGL_METHOD_NAME);
8008 return cStatusSoftFailure;
8011 GL_ENTRYPOINT(glSeparableFilter2D)(target, internalformat, width, height, format, type, row, column);
8015 case VOGL_ENTRYPOINT_glNamedProgramLocalParameters4fvEXT:
8017 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8018 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8020 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));
8024 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4iEXT:
8026 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8027 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8029 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));
8032 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4ivEXT:
8034 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8035 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8037 GL_ENTRYPOINT(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));
8041 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4ivEXT:
8043 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8044 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8046 GL_ENTRYPOINT(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));
8049 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uiEXT:
8051 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8052 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8054 GL_ENTRYPOINT(glNamedProgramLocalParameterI4uiEXT)(replay_program, trace_packet.get_param_value<GLenum>(1), trace_packet.get_param_value<GLuint>(2),
8055 trace_packet.get_param_value<GLuint>(3), trace_packet.get_param_value<GLuint>(4),
8056 trace_packet.get_param_value<GLuint>(5), trace_packet.get_param_value<GLuint>(6));
8059 case VOGL_ENTRYPOINT_glNamedProgramLocalParameterI4uivEXT:
8061 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8062 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8064 GL_ENTRYPOINT(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));
8067 case VOGL_ENTRYPOINT_glNamedProgramLocalParametersI4uivEXT:
8069 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8070 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8072 GL_ENTRYPOINT(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));
8075 case VOGL_ENTRYPOINT_glNamedProgramLocalParameter4fvEXT:
8077 GLuint trace_program = trace_packet.get_param_value<GLuint>(0);
8078 GLuint replay_program = map_handle(get_shared_state()->m_arb_programs, trace_program);
8080 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));
8083 case VOGL_ENTRYPOINT_glGetTexEnvfv:
8085 if (!benchmark_mode())
8087 GLenum target = trace_packet.get_param_value<GLenum>(0);
8088 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8089 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8091 GLfloat vals[4] = { 0, 0, 0, 0 };
8093 int n = g_gl_enums.get_pname_count(pname);
8094 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8096 GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, vals);
8100 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8102 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8104 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8110 case VOGL_ENTRYPOINT_glGetTexEnviv:
8112 if (!benchmark_mode())
8114 GLenum target = trace_packet.get_param_value<GLenum>(0);
8115 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8116 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8118 GLint vals[4] = { 0, 0, 0, 0 };
8120 int n = g_gl_enums.get_pname_count(pname);
8121 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8123 GL_ENTRYPOINT(glGetTexEnviv)(target, pname, vals);
8127 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8129 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8131 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8137 case VOGL_ENTRYPOINT_glGetTexGendv:
8139 if (!benchmark_mode())
8141 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8142 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8143 const GLdouble *pParams = trace_packet.get_param_client_memory<GLdouble>(2);
8145 GLdouble vals[4] = { 0, 0, 0, 0 };
8147 int n = g_gl_enums.get_pname_count(pname);
8148 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8150 GL_ENTRYPOINT(glGetTexGendv)(coord, pname, vals);
8154 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8156 else if (memcmp(pParams, vals, n * sizeof(GLdouble)) != 0)
8158 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8164 case VOGL_ENTRYPOINT_glGetTexGenfv:
8166 if (!benchmark_mode())
8168 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8169 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8170 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8172 GLfloat vals[4] = { 0, 0, 0, 0 };
8174 int n = g_gl_enums.get_pname_count(pname);
8175 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8177 GL_ENTRYPOINT(glGetTexGenfv)(coord, pname, vals);
8181 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8183 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8185 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8191 case VOGL_ENTRYPOINT_glGetTexGeniv:
8193 if (!benchmark_mode())
8195 GLenum coord = trace_packet.get_param_value<GLenum>(0);
8196 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8197 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8199 GLint vals[4] = { 0, 0, 0, 0 };
8201 int n = g_gl_enums.get_pname_count(pname);
8202 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8204 GL_ENTRYPOINT(glGetTexGeniv)(coord, pname, vals);
8208 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8210 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8212 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8218 case VOGL_ENTRYPOINT_glGetLightfv:
8220 if (!benchmark_mode())
8222 GLenum light = trace_packet.get_param_value<GLenum>(0);
8223 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8224 const GLfloat *pParams = trace_packet.get_param_client_memory<GLfloat>(2);
8226 GLfloat vals[4] = { 0, 0, 0, 0 };
8228 int n = g_gl_enums.get_pname_count(pname);
8229 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8231 GL_ENTRYPOINT(glGetLightfv)(light, pname, vals);
8235 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8237 else if (memcmp(pParams, vals, n * sizeof(GLfloat)) != 0)
8239 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8245 case VOGL_ENTRYPOINT_glGetLightiv:
8247 if (!benchmark_mode())
8249 GLenum light = trace_packet.get_param_value<GLenum>(0);
8250 GLenum pname = trace_packet.get_param_value<GLenum>(1);
8251 const GLint *pParams = trace_packet.get_param_client_memory<GLint>(2);
8253 GLint vals[4] = { 0, 0, 0, 0 };
8255 int n = g_gl_enums.get_pname_count(pname);
8256 VOGL_ASSERT(n <= (int)VOGL_ARRAY_SIZE(vals));
8258 GL_ENTRYPOINT(glGetLightiv)(light, pname, vals);
8262 process_entrypoint_error("%s: Unable to compute element count for pname 0x%08X\n", VOGL_METHOD_NAME, pname);
8264 else if (memcmp(pParams, vals, n * sizeof(GLint)) != 0)
8266 process_entrypoint_error("%s: Replay divergence detected\n", VOGL_METHOD_NAME);
8272 case VOGL_ENTRYPOINT_glSelectBuffer:
8274 GLsizei size = trace_packet.get_param_value<GLsizei>(0);
8276 if (m_pCur_context_state->m_select_buffer.try_resize(size))
8278 GL_ENTRYPOINT(glSelectBuffer)(size, m_pCur_context_state->m_select_buffer.get_ptr());
8282 process_entrypoint_error("%s: Failed resizing context's select buffer\n", VOGL_METHOD_NAME);
8287 case VOGL_ENTRYPOINT_glClearBufferfv:
8289 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferfv;
8291 // TODO: Check params
8293 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferfv;
8297 case VOGL_ENTRYPOINT_glClearBufferiv:
8299 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferiv;
8301 // TODO: Check params
8303 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferiv;
8307 case VOGL_ENTRYPOINT_glClearBufferuiv:
8309 VOGL_REPLAY_LOAD_PARAMS_HELPER_glClearBufferuiv;
8311 // TODO: Check params
8313 VOGL_REPLAY_CALL_GL_HELPER_glClearBufferuiv;
8317 case VOGL_ENTRYPOINT_glTexBuffer:
8318 case VOGL_ENTRYPOINT_glTexBufferARB:
8319 case VOGL_ENTRYPOINT_glTexBufferEXT:
8321 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTexBuffer;
8323 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8325 SWITCH_GL_ENTRYPOINT3_VOID(glTexBuffer, glTexBufferARB, glTexBufferEXT, target, internalformat, buffer);
8328 case VOGL_ENTRYPOINT_glBeginConditionalRender:
8330 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginConditionalRender;
8332 id = map_handle(get_shared_state()->m_queries, id);
8334 VOGL_REPLAY_CALL_GL_HELPER_glBeginConditionalRender;
8337 case VOGL_ENTRYPOINT_glEndConditionalRender:
8339 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndConditionalRender;
8341 VOGL_REPLAY_CALL_GL_HELPER_glEndConditionalRender;
8344 case VOGL_ENTRYPOINT_glBeginTransformFeedback:
8346 VOGL_REPLAY_LOAD_PARAMS_HELPER_glBeginTransformFeedback;
8348 VOGL_REPLAY_CALL_GL_HELPER_glBeginTransformFeedback;
8351 case VOGL_ENTRYPOINT_glEndTransformFeedback:
8353 VOGL_REPLAY_LOAD_PARAMS_HELPER_glEndTransformFeedback;
8355 VOGL_REPLAY_CALL_GL_HELPER_glEndTransformFeedback;
8359 case VOGL_ENTRYPOINT_glTransformFeedbackVaryings:
8361 VOGL_REPLAY_LOAD_PARAMS_HELPER_glTransformFeedbackVaryings;
8362 VOGL_NOTE_UNUSED(pTrace_varyings);
8364 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8366 dynamic_string_array replay_varyings(count);
8368 const key_value_map &key_value_map = trace_packet.get_key_value_map();
8369 const value_to_value_hash_map &hash_map = key_value_map.get_map();
8371 for (value_to_value_hash_map::const_iterator it = hash_map.begin(); it != hash_map.end(); ++it)
8373 int key_index = it->first.get_int();
8375 if ((key_index >= 0) && (key_index < count))
8377 const dynamic_string *pName = it->second.get_string_ptr();
8380 replay_varyings[key_index] = pName ? *pName : "";
8388 vogl::vector<const GLchar *> str_ptrs(count);
8389 for (int i = 0; i < count; i++)
8390 str_ptrs[i] = reinterpret_cast<const GLchar *>(replay_varyings[i].get_ptr());
8392 GLchar *const *pReplay_varyings = (GLchar *const *)(str_ptrs.get_ptr());
8394 VOGL_REPLAY_CALL_GL_HELPER_glTransformFeedbackVaryings;
8398 case VOGL_ENTRYPOINT_glUniformBufferEXT:
8400 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBufferEXT;
8402 GLuint trace_program = program;
8404 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8405 location = determine_uniform_replay_location(trace_program, location);
8406 buffer = map_handle(get_shared_state()->m_buffers, buffer);
8408 VOGL_REPLAY_CALL_GL_HELPER_glUniformBufferEXT;
8411 case VOGL_ENTRYPOINT_glUniformBlockBinding:
8413 // TODO: Does any of this other stuff need to be remapped?
8414 VOGL_REPLAY_LOAD_PARAMS_HELPER_glUniformBlockBinding;
8416 program = map_handle(get_shared_state()->m_shadow_state.m_objs, program);
8418 VOGL_REPLAY_CALL_GL_HELPER_glUniformBlockBinding;
8421 case VOGL_ENTRYPOINT_glFrameTerminatorGREMEDY:
8423 // TODO - we need to hook up this extension to the tracer
8426 case VOGL_ENTRYPOINT_glStringMarkerGREMEDY:
8428 // TODO - we need to hook up this extension to the tracer
8431 case VOGL_ENTRYPOINT_glDebugMessageCallbackARB:
8432 case VOGL_ENTRYPOINT_glGetDebugMessageLogARB:
8433 case VOGL_ENTRYPOINT_glDebugMessageControlARB:
8434 case VOGL_ENTRYPOINT_glDebugMessageInsertARB:
8439 case VOGL_ENTRYPOINT_glAreTexturesResident:
8440 case VOGL_ENTRYPOINT_glAreTexturesResidentEXT:
8441 case VOGL_ENTRYPOINT_glGetActiveAtomicCounterBufferiv:
8442 case VOGL_ENTRYPOINT_glGetActiveAttribARB:
8443 case VOGL_ENTRYPOINT_glGetActiveSubroutineName:
8444 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformName:
8445 case VOGL_ENTRYPOINT_glGetActiveSubroutineUniformiv:
8446 case VOGL_ENTRYPOINT_glGetActiveUniformARB:
8447 case VOGL_ENTRYPOINT_glGetActiveUniformBlockName:
8448 case VOGL_ENTRYPOINT_glGetActiveUniformBlockiv:
8449 case VOGL_ENTRYPOINT_glGetActiveUniformName:
8450 case VOGL_ENTRYPOINT_glGetActiveUniformsiv:
8451 case VOGL_ENTRYPOINT_glGetActiveVaryingNV:
8452 case VOGL_ENTRYPOINT_glGetArrayObjectfvATI:
8453 case VOGL_ENTRYPOINT_glGetArrayObjectivATI:
8454 case VOGL_ENTRYPOINT_glGetAttachedObjectsARB:
8455 case VOGL_ENTRYPOINT_glGetAttribLocationARB:
8456 case VOGL_ENTRYPOINT_glGetBooleanIndexedvEXT:
8457 case VOGL_ENTRYPOINT_glGetBooleani_v:
8458 case VOGL_ENTRYPOINT_glGetBufferParameteri64v:
8459 case VOGL_ENTRYPOINT_glGetBufferParameterivARB:
8460 case VOGL_ENTRYPOINT_glGetBufferParameterui64vNV:
8461 case VOGL_ENTRYPOINT_glGetBufferPointervARB:
8462 case VOGL_ENTRYPOINT_glGetBufferSubDataARB:
8463 case VOGL_ENTRYPOINT_glGetClipPlanefOES:
8464 case VOGL_ENTRYPOINT_glGetClipPlanexOES:
8465 case VOGL_ENTRYPOINT_glGetColorTable:
8466 case VOGL_ENTRYPOINT_glGetColorTableEXT:
8467 case VOGL_ENTRYPOINT_glGetColorTableParameterfv:
8468 case VOGL_ENTRYPOINT_glGetColorTableParameterfvEXT:
8469 case VOGL_ENTRYPOINT_glGetColorTableParameterfvSGI:
8470 case VOGL_ENTRYPOINT_glGetColorTableParameteriv:
8471 case VOGL_ENTRYPOINT_glGetColorTableParameterivEXT:
8472 case VOGL_ENTRYPOINT_glGetColorTableParameterivSGI:
8473 case VOGL_ENTRYPOINT_glGetColorTableSGI:
8474 case VOGL_ENTRYPOINT_glGetCombinerInputParameterfvNV:
8475 case VOGL_ENTRYPOINT_glGetCombinerInputParameterivNV:
8476 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterfvNV:
8477 case VOGL_ENTRYPOINT_glGetCombinerOutputParameterivNV:
8478 case VOGL_ENTRYPOINT_glGetCombinerStageParameterfvNV:
8479 case VOGL_ENTRYPOINT_glGetCompressedMultiTexImageEXT:
8480 case VOGL_ENTRYPOINT_glGetCompressedTexImage:
8481 case VOGL_ENTRYPOINT_glGetCompressedTexImageARB:
8482 case VOGL_ENTRYPOINT_glGetCompressedTextureImageEXT:
8483 case VOGL_ENTRYPOINT_glGetConvolutionFilter:
8484 case VOGL_ENTRYPOINT_glGetConvolutionFilterEXT:
8485 case VOGL_ENTRYPOINT_glGetConvolutionParameterfv:
8486 case VOGL_ENTRYPOINT_glGetConvolutionParameterfvEXT:
8487 case VOGL_ENTRYPOINT_glGetConvolutionParameteriv:
8488 case VOGL_ENTRYPOINT_glGetConvolutionParameterivEXT:
8489 case VOGL_ENTRYPOINT_glGetConvolutionParameterxvOES:
8490 case VOGL_ENTRYPOINT_glGetDebugMessageLog:
8491 case VOGL_ENTRYPOINT_glGetDebugMessageLogAMD:
8492 case VOGL_ENTRYPOINT_glGetDetailTexFuncSGIS:
8493 case VOGL_ENTRYPOINT_glGetDoubleIndexedvEXT:
8494 case VOGL_ENTRYPOINT_glGetDoublei_v:
8495 case VOGL_ENTRYPOINT_glGetFenceivNV:
8496 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterfvNV:
8497 case VOGL_ENTRYPOINT_glGetFinalCombinerInputParameterivNV:
8498 case VOGL_ENTRYPOINT_glGetFixedvOES:
8499 case VOGL_ENTRYPOINT_glGetFloatIndexedvEXT:
8500 case VOGL_ENTRYPOINT_glGetFloati_v:
8501 case VOGL_ENTRYPOINT_glGetFogFuncSGIS:
8502 case VOGL_ENTRYPOINT_glGetFragDataIndex:
8503 case VOGL_ENTRYPOINT_glGetFragDataLocation:
8504 case VOGL_ENTRYPOINT_glGetFragDataLocationEXT:
8505 case VOGL_ENTRYPOINT_glGetFragmentLightfvSGIX:
8506 case VOGL_ENTRYPOINT_glGetFragmentLightivSGIX:
8507 case VOGL_ENTRYPOINT_glGetFragmentMaterialfvSGIX:
8508 case VOGL_ENTRYPOINT_glGetFragmentMaterialivSGIX:
8509 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameteriv:
8510 case VOGL_ENTRYPOINT_glGetFramebufferAttachmentParameterivEXT:
8511 case VOGL_ENTRYPOINT_glGetFramebufferParameteriv:
8512 case VOGL_ENTRYPOINT_glGetFramebufferParameterivEXT:
8513 case VOGL_ENTRYPOINT_glGetGraphicsResetStatusARB:
8514 case VOGL_ENTRYPOINT_glGetHandleARB:
8515 case VOGL_ENTRYPOINT_glGetHistogram:
8516 case VOGL_ENTRYPOINT_glGetHistogramEXT:
8517 case VOGL_ENTRYPOINT_glGetHistogramParameterfv:
8518 case VOGL_ENTRYPOINT_glGetHistogramParameterfvEXT:
8519 case VOGL_ENTRYPOINT_glGetHistogramParameteriv:
8520 case VOGL_ENTRYPOINT_glGetHistogramParameterivEXT:
8521 case VOGL_ENTRYPOINT_glGetHistogramParameterxvOES:
8522 case VOGL_ENTRYPOINT_glGetImageHandleNV:
8523 case VOGL_ENTRYPOINT_glGetImageTransformParameterfvHP:
8524 case VOGL_ENTRYPOINT_glGetImageTransformParameterivHP:
8525 case VOGL_ENTRYPOINT_glGetInstrumentsSGIX:
8526 case VOGL_ENTRYPOINT_glGetInteger64i_v:
8527 case VOGL_ENTRYPOINT_glGetInteger64v:
8528 case VOGL_ENTRYPOINT_glGetIntegerIndexedvEXT:
8529 case VOGL_ENTRYPOINT_glGetIntegeri_v:
8530 case VOGL_ENTRYPOINT_glGetIntegerui64i_vNV:
8531 case VOGL_ENTRYPOINT_glGetIntegerui64vNV:
8532 case VOGL_ENTRYPOINT_glGetInternalformati64v:
8533 case VOGL_ENTRYPOINT_glGetInternalformativ:
8534 case VOGL_ENTRYPOINT_glGetInvariantBooleanvEXT:
8535 case VOGL_ENTRYPOINT_glGetInvariantFloatvEXT:
8536 case VOGL_ENTRYPOINT_glGetInvariantIntegervEXT:
8537 case VOGL_ENTRYPOINT_glGetLightxOES:
8538 case VOGL_ENTRYPOINT_glGetListParameterfvSGIX:
8539 case VOGL_ENTRYPOINT_glGetListParameterivSGIX:
8540 case VOGL_ENTRYPOINT_glGetLocalConstantBooleanvEXT:
8541 case VOGL_ENTRYPOINT_glGetLocalConstantFloatvEXT:
8542 case VOGL_ENTRYPOINT_glGetLocalConstantIntegervEXT:
8543 case VOGL_ENTRYPOINT_glGetMapAttribParameterfvNV:
8544 case VOGL_ENTRYPOINT_glGetMapAttribParameterivNV:
8545 case VOGL_ENTRYPOINT_glGetMapControlPointsNV:
8546 case VOGL_ENTRYPOINT_glGetMapParameterfvNV:
8547 case VOGL_ENTRYPOINT_glGetMapParameterivNV:
8548 case VOGL_ENTRYPOINT_glGetMapdv:
8549 case VOGL_ENTRYPOINT_glGetMapfv:
8550 case VOGL_ENTRYPOINT_glGetMapiv:
8551 case VOGL_ENTRYPOINT_glGetMapxvOES:
8552 case VOGL_ENTRYPOINT_glGetMaterialfv:
8553 case VOGL_ENTRYPOINT_glGetMaterialiv:
8554 case VOGL_ENTRYPOINT_glGetMaterialxOES:
8555 case VOGL_ENTRYPOINT_glGetMinmax:
8556 case VOGL_ENTRYPOINT_glGetMinmaxEXT:
8557 case VOGL_ENTRYPOINT_glGetMinmaxParameterfv:
8558 case VOGL_ENTRYPOINT_glGetMinmaxParameterfvEXT:
8559 case VOGL_ENTRYPOINT_glGetMinmaxParameteriv:
8560 case VOGL_ENTRYPOINT_glGetMinmaxParameterivEXT:
8561 case VOGL_ENTRYPOINT_glGetMultiTexEnvfvEXT:
8562 case VOGL_ENTRYPOINT_glGetMultiTexEnvivEXT:
8563 case VOGL_ENTRYPOINT_glGetMultiTexGendvEXT:
8564 case VOGL_ENTRYPOINT_glGetMultiTexGenfvEXT:
8565 case VOGL_ENTRYPOINT_glGetMultiTexGenivEXT:
8566 case VOGL_ENTRYPOINT_glGetMultiTexImageEXT:
8567 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterfvEXT:
8568 case VOGL_ENTRYPOINT_glGetMultiTexLevelParameterivEXT:
8569 case VOGL_ENTRYPOINT_glGetMultiTexParameterIivEXT:
8570 case VOGL_ENTRYPOINT_glGetMultiTexParameterIuivEXT:
8571 case VOGL_ENTRYPOINT_glGetMultiTexParameterfvEXT:
8572 case VOGL_ENTRYPOINT_glGetMultiTexParameterivEXT:
8573 case VOGL_ENTRYPOINT_glGetMultisamplefv:
8574 case VOGL_ENTRYPOINT_glGetMultisamplefvNV:
8575 case VOGL_ENTRYPOINT_glGetNamedBufferParameterivEXT:
8576 case VOGL_ENTRYPOINT_glGetNamedBufferParameterui64vNV:
8577 case VOGL_ENTRYPOINT_glGetNamedBufferPointervEXT:
8578 case VOGL_ENTRYPOINT_glGetNamedBufferSubDataEXT:
8579 case VOGL_ENTRYPOINT_glGetNamedFramebufferAttachmentParameterivEXT:
8580 case VOGL_ENTRYPOINT_glGetNamedFramebufferParameterivEXT:
8581 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIivEXT:
8582 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterIuivEXT:
8583 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterdvEXT:
8584 case VOGL_ENTRYPOINT_glGetNamedProgramLocalParameterfvEXT:
8585 case VOGL_ENTRYPOINT_glGetNamedProgramStringEXT:
8586 case VOGL_ENTRYPOINT_glGetNamedProgramivEXT:
8587 case VOGL_ENTRYPOINT_glGetNamedRenderbufferParameterivEXT:
8588 case VOGL_ENTRYPOINT_glGetNamedStringARB:
8589 case VOGL_ENTRYPOINT_glGetNamedStringivARB:
8590 case VOGL_ENTRYPOINT_glGetObjectBufferfvATI:
8591 case VOGL_ENTRYPOINT_glGetObjectBufferivATI:
8592 case VOGL_ENTRYPOINT_glGetObjectLabel:
8593 case VOGL_ENTRYPOINT_glGetObjectParameterfvARB:
8594 case VOGL_ENTRYPOINT_glGetObjectParameterivAPPLE:
8595 case VOGL_ENTRYPOINT_glGetObjectPtrLabel:
8596 case VOGL_ENTRYPOINT_glGetOcclusionQueryivNV:
8597 case VOGL_ENTRYPOINT_glGetOcclusionQueryuivNV:
8598 case VOGL_ENTRYPOINT_glGetPathColorGenfvNV:
8599 case VOGL_ENTRYPOINT_glGetPathColorGenivNV:
8600 case VOGL_ENTRYPOINT_glGetPathCommandsNV:
8601 case VOGL_ENTRYPOINT_glGetPathCoordsNV:
8602 case VOGL_ENTRYPOINT_glGetPathDashArrayNV:
8603 case VOGL_ENTRYPOINT_glGetPathLengthNV:
8604 case VOGL_ENTRYPOINT_glGetPathMetricRangeNV:
8605 case VOGL_ENTRYPOINT_glGetPathMetricsNV:
8606 case VOGL_ENTRYPOINT_glGetPathParameterfvNV:
8607 case VOGL_ENTRYPOINT_glGetPathParameterivNV:
8608 case VOGL_ENTRYPOINT_glGetPathSpacingNV:
8609 case VOGL_ENTRYPOINT_glGetPathTexGenfvNV:
8610 case VOGL_ENTRYPOINT_glGetPathTexGenivNV:
8611 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterDataAMD:
8612 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterInfoAMD:
8613 case VOGL_ENTRYPOINT_glGetPerfMonitorCounterStringAMD:
8614 case VOGL_ENTRYPOINT_glGetPerfMonitorCountersAMD:
8615 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupStringAMD:
8616 case VOGL_ENTRYPOINT_glGetPerfMonitorGroupsAMD:
8617 case VOGL_ENTRYPOINT_glGetPixelMapfv:
8618 case VOGL_ENTRYPOINT_glGetPixelMapuiv:
8619 case VOGL_ENTRYPOINT_glGetPixelMapusv:
8620 case VOGL_ENTRYPOINT_glGetPixelMapxv:
8621 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterfvSGIS:
8622 case VOGL_ENTRYPOINT_glGetPixelTexGenParameterivSGIS:
8623 case VOGL_ENTRYPOINT_glGetPixelTransformParameterfvEXT:
8624 case VOGL_ENTRYPOINT_glGetPixelTransformParameterivEXT:
8625 case VOGL_ENTRYPOINT_glGetPointerIndexedvEXT:
8626 case VOGL_ENTRYPOINT_glGetPointervEXT:
8627 case VOGL_ENTRYPOINT_glGetPolygonStipple:
8628 case VOGL_ENTRYPOINT_glGetProgramBinary:
8629 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIivNV:
8630 case VOGL_ENTRYPOINT_glGetProgramEnvParameterIuivNV:
8631 case VOGL_ENTRYPOINT_glGetProgramEnvParameterdvARB:
8632 case VOGL_ENTRYPOINT_glGetProgramEnvParameterfvARB:
8633 case VOGL_ENTRYPOINT_glGetProgramInterfaceiv:
8634 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIivNV:
8635 case VOGL_ENTRYPOINT_glGetProgramLocalParameterIuivNV:
8636 case VOGL_ENTRYPOINT_glGetProgramLocalParameterdvARB:
8637 case VOGL_ENTRYPOINT_glGetProgramLocalParameterfvARB:
8638 case VOGL_ENTRYPOINT_glGetProgramNamedParameterdvNV:
8639 case VOGL_ENTRYPOINT_glGetProgramNamedParameterfvNV:
8640 case VOGL_ENTRYPOINT_glGetProgramParameterdvNV:
8641 case VOGL_ENTRYPOINT_glGetProgramParameterfvNV:
8642 case VOGL_ENTRYPOINT_glGetProgramPipelineInfoLog:
8643 case VOGL_ENTRYPOINT_glGetProgramPipelineiv:
8644 case VOGL_ENTRYPOINT_glGetProgramResourceIndex:
8645 case VOGL_ENTRYPOINT_glGetProgramResourceLocation:
8646 case VOGL_ENTRYPOINT_glGetProgramResourceLocationIndex:
8647 case VOGL_ENTRYPOINT_glGetProgramResourceName:
8648 case VOGL_ENTRYPOINT_glGetProgramResourceiv:
8649 case VOGL_ENTRYPOINT_glGetProgramStageiv:
8650 case VOGL_ENTRYPOINT_glGetProgramStringARB:
8651 case VOGL_ENTRYPOINT_glGetProgramStringNV:
8652 case VOGL_ENTRYPOINT_glGetProgramSubroutineParameteruivNV:
8653 case VOGL_ENTRYPOINT_glGetProgramivNV:
8654 case VOGL_ENTRYPOINT_glGetQueryIndexediv:
8655 case VOGL_ENTRYPOINT_glGetQueryObjecti64vEXT:
8656 case VOGL_ENTRYPOINT_glGetQueryObjectui64vEXT:
8657 case VOGL_ENTRYPOINT_glGetQueryiv:
8658 case VOGL_ENTRYPOINT_glGetQueryivARB:
8659 case VOGL_ENTRYPOINT_glGetSamplerParameterIiv:
8660 case VOGL_ENTRYPOINT_glGetSamplerParameterIuiv:
8661 case VOGL_ENTRYPOINT_glGetSamplerParameterfv:
8662 case VOGL_ENTRYPOINT_glGetSamplerParameteriv:
8663 case VOGL_ENTRYPOINT_glGetSeparableFilter:
8664 case VOGL_ENTRYPOINT_glGetSeparableFilterEXT:
8665 case VOGL_ENTRYPOINT_glGetShaderPrecisionFormat:
8666 case VOGL_ENTRYPOINT_glGetShaderSource:
8667 case VOGL_ENTRYPOINT_glGetShaderSourceARB:
8668 case VOGL_ENTRYPOINT_glGetSharpenTexFuncSGIS:
8669 case VOGL_ENTRYPOINT_glGetSubroutineIndex:
8670 case VOGL_ENTRYPOINT_glGetSubroutineUniformLocation:
8671 case VOGL_ENTRYPOINT_glGetSynciv:
8672 case VOGL_ENTRYPOINT_glGetTexBumpParameterfvATI:
8673 case VOGL_ENTRYPOINT_glGetTexBumpParameterivATI:
8674 case VOGL_ENTRYPOINT_glGetTexEnvxvOES:
8675 case VOGL_ENTRYPOINT_glGetTexFilterFuncSGIS:
8676 case VOGL_ENTRYPOINT_glGetTexGenxvOES:
8677 case VOGL_ENTRYPOINT_glGetTexImage:
8678 case VOGL_ENTRYPOINT_glGetTexLevelParameterxvOES:
8679 case VOGL_ENTRYPOINT_glGetTexParameterIivEXT:
8680 case VOGL_ENTRYPOINT_glGetTexParameterIuivEXT:
8681 case VOGL_ENTRYPOINT_glGetTexParameterPointervAPPLE:
8682 case VOGL_ENTRYPOINT_glGetTexParameterxvOES:
8683 case VOGL_ENTRYPOINT_glGetTextureHandleNV:
8684 case VOGL_ENTRYPOINT_glGetTextureImageEXT:
8685 case VOGL_ENTRYPOINT_glGetTextureLevelParameterfvEXT:
8686 case VOGL_ENTRYPOINT_glGetTextureLevelParameterivEXT:
8687 case VOGL_ENTRYPOINT_glGetTextureParameterIivEXT:
8688 case VOGL_ENTRYPOINT_glGetTextureParameterIuivEXT:
8689 case VOGL_ENTRYPOINT_glGetTextureParameterfvEXT:
8690 case VOGL_ENTRYPOINT_glGetTextureParameterivEXT:
8691 case VOGL_ENTRYPOINT_glGetTextureSamplerHandleNV:
8692 case VOGL_ENTRYPOINT_glGetTrackMatrixivNV:
8693 case VOGL_ENTRYPOINT_glGetTransformFeedbackVarying:
8694 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingEXT:
8695 case VOGL_ENTRYPOINT_glGetTransformFeedbackVaryingNV:
8696 case VOGL_ENTRYPOINT_glGetUniformBlockIndex:
8697 case VOGL_ENTRYPOINT_glGetUniformBufferSizeEXT:
8698 case VOGL_ENTRYPOINT_glGetUniformIndices:
8699 case VOGL_ENTRYPOINT_glGetUniformOffsetEXT:
8700 case VOGL_ENTRYPOINT_glGetUniformSubroutineuiv:
8701 case VOGL_ENTRYPOINT_glGetUniformdv:
8702 case VOGL_ENTRYPOINT_glGetUniformfv:
8703 case VOGL_ENTRYPOINT_glGetUniformfvARB:
8704 case VOGL_ENTRYPOINT_glGetUniformi64vNV:
8705 case VOGL_ENTRYPOINT_glGetUniformiv:
8706 case VOGL_ENTRYPOINT_glGetUniformivARB:
8707 case VOGL_ENTRYPOINT_glGetUniformui64vNV:
8708 case VOGL_ENTRYPOINT_glGetUniformuiv:
8709 case VOGL_ENTRYPOINT_glGetUniformuivEXT:
8710 case VOGL_ENTRYPOINT_glGetVariantArrayObjectfvATI:
8711 case VOGL_ENTRYPOINT_glGetVariantArrayObjectivATI:
8712 case VOGL_ENTRYPOINT_glGetVariantBooleanvEXT:
8713 case VOGL_ENTRYPOINT_glGetVariantFloatvEXT:
8714 case VOGL_ENTRYPOINT_glGetVariantIntegervEXT:
8715 case VOGL_ENTRYPOINT_glGetVariantPointervEXT:
8716 case VOGL_ENTRYPOINT_glGetVaryingLocationNV:
8717 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectfvATI:
8718 case VOGL_ENTRYPOINT_glGetVertexAttribArrayObjectivATI:
8719 case VOGL_ENTRYPOINT_glGetVertexAttribLdv:
8720 case VOGL_ENTRYPOINT_glGetVertexAttribLdvEXT:
8721 case VOGL_ENTRYPOINT_glGetVertexAttribLi64vNV:
8722 case VOGL_ENTRYPOINT_glGetVertexAttribLui64vNV:
8723 case VOGL_ENTRYPOINT_glGetVertexAttribPointerv:
8724 case VOGL_ENTRYPOINT_glGetVertexAttribPointervARB:
8725 case VOGL_ENTRYPOINT_glGetVertexAttribPointervNV:
8726 case VOGL_ENTRYPOINT_glGetVertexAttribdvARB:
8727 case VOGL_ENTRYPOINT_glGetVertexAttribdvNV:
8728 case VOGL_ENTRYPOINT_glGetVertexAttribfvARB:
8729 case VOGL_ENTRYPOINT_glGetVertexAttribfvNV:
8730 case VOGL_ENTRYPOINT_glGetVertexAttribivARB:
8731 case VOGL_ENTRYPOINT_glGetVertexAttribivNV:
8732 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamdvNV:
8733 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamfvNV:
8734 case VOGL_ENTRYPOINT_glGetVideoCaptureStreamivNV:
8735 case VOGL_ENTRYPOINT_glGetVideoCaptureivNV:
8736 case VOGL_ENTRYPOINT_glGetVideoi64vNV:
8737 case VOGL_ENTRYPOINT_glGetVideoivNV:
8738 case VOGL_ENTRYPOINT_glGetVideoui64vNV:
8739 case VOGL_ENTRYPOINT_glGetVideouivNV:
8740 case VOGL_ENTRYPOINT_glGetnColorTableARB:
8741 case VOGL_ENTRYPOINT_glGetnCompressedTexImageARB:
8742 case VOGL_ENTRYPOINT_glGetnConvolutionFilterARB:
8743 case VOGL_ENTRYPOINT_glGetnHistogramARB:
8744 case VOGL_ENTRYPOINT_glGetnMapdvARB:
8745 case VOGL_ENTRYPOINT_glGetnMapfvARB:
8746 case VOGL_ENTRYPOINT_glGetnMapivARB:
8747 case VOGL_ENTRYPOINT_glGetnMinmaxARB:
8748 case VOGL_ENTRYPOINT_glGetnPixelMapfvARB:
8749 case VOGL_ENTRYPOINT_glGetnPixelMapuivARB:
8750 case VOGL_ENTRYPOINT_glGetnPixelMapusvARB:
8751 case VOGL_ENTRYPOINT_glGetnPolygonStippleARB:
8752 case VOGL_ENTRYPOINT_glGetnSeparableFilterARB:
8753 case VOGL_ENTRYPOINT_glGetnTexImageARB:
8754 case VOGL_ENTRYPOINT_glGetnUniformdvARB:
8755 case VOGL_ENTRYPOINT_glGetnUniformfvARB:
8756 case VOGL_ENTRYPOINT_glGetnUniformivARB:
8757 case VOGL_ENTRYPOINT_glGetnUniformuivARB:
8758 case VOGL_ENTRYPOINT_glIsBufferARB:
8759 case VOGL_ENTRYPOINT_glIsEnabledIndexedEXT:
8760 case VOGL_ENTRYPOINT_glIsQueryARB:
8761 case VOGL_ENTRYPOINT_glIsSync:
8762 case VOGL_ENTRYPOINT_glPrioritizeTextures:
8763 case VOGL_ENTRYPOINT_glPrioritizeTexturesEXT:
8765 if (!(g_vogl_entrypoint_descs[entrypoint_id].m_flags & cGLEFPrintedUnimplementedWarning))
8767 process_entrypoint_warning("%s: TODO: Implement glGet() function %s\n", VOGL_METHOD_NAME, g_vogl_entrypoint_descs[entrypoint_id].m_pName);
8769 g_vogl_entrypoint_descs[entrypoint_id].m_flags |= cGLEFPrintedUnimplementedWarning;
8775 if (g_vogl_entrypoint_descs[entrypoint_id].m_is_whitelisted)
8776 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);
8778 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);
8779 return cStatusSoftFailure;
8783 m_last_processed_call_counter = trace_packet.get_call_counter();
8785 if (!m_pCur_context_state->m_inside_gl_begin)
8787 if (check_gl_error())
8788 return cStatusGLError;
8791 if (vogl_is_draw_entrypoint(entrypoint_id) || vogl_is_clear_entrypoint(entrypoint_id) || (entrypoint_id == VOGL_ENTRYPOINT_glBitmap))
8793 if ((status = post_draw_call()) != cStatusOK)
8800 //----------------------------------------------------------------------------------------------------------------------
8801 // vogl_gl_replayer::snapshot_backbuffer
8802 //----------------------------------------------------------------------------------------------------------------------
8803 void vogl_gl_replayer::snapshot_backbuffer()
8807 if (!m_pCur_context_state)
8809 vogl_warning_printf("%s: Can't take snapshot without an active context\n", VOGL_METHOD_NAME);
8813 uint recorded_width = m_pWindow->get_width();
8814 uint recorded_height = m_pWindow->get_height();
8816 uint width = 0, height = 0;
8817 m_pWindow->get_actual_dimensions(width, height);
8819 VOGL_ASSERT((recorded_width == width) && (recorded_height == height));
8820 VOGL_NOTE_UNUSED(recorded_width);
8821 VOGL_NOTE_UNUSED(recorded_height);
8823 m_screenshot_buffer.resize(width * height * 3);
8825 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);
8828 process_entrypoint_error("%s: Failed calling glReadPixels() to take screenshot\n", VOGL_METHOD_NAME);
8831 if (m_flags & cGLReplayerDumpScreenshots)
8833 size_t png_size = 0;
8834 void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(m_screenshot_buffer.get_ptr(), width, height, 3, &png_size, 1, true);
8836 dynamic_string screenshot_filename(cVarArg, "%s_%07u.png", m_screenshot_prefix.get_ptr(), m_total_swaps);
8837 if (!file_utils::write_buf_to_file(screenshot_filename.get_ptr(), pPNG_data, png_size))
8839 process_entrypoint_error("Failed writing PNG screenshot to file %s\n", screenshot_filename.get_ptr());
8843 vogl_message_printf("Wrote screenshot to file %s\n", screenshot_filename.get_ptr());
8849 if ((m_flags & cGLReplayerDumpBackbufferHashes) || (m_flags & cGLReplayerHashBackbuffer))
8851 uint64_t backbuffer_crc64;
8853 if (m_flags & cGLReplayerSumHashing)
8855 backbuffer_crc64 = calc_sum64(m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
8859 backbuffer_crc64 = calc_crc64(CRC64_INIT, m_screenshot_buffer.get_ptr(), m_screenshot_buffer.size());
8862 vogl_printf("Frame %u hash: 0x%016" PRIX64 "\n", m_frame_index, backbuffer_crc64);
8864 if (m_backbuffer_hash_filename.has_content())
8866 FILE *pFile = vogl_fopen(m_backbuffer_hash_filename.get_ptr(), "a");
8868 vogl_error_printf("Failed writing to backbuffer hash file %s\n", m_backbuffer_hash_filename.get_ptr());
8871 vogl_fprintf(pFile, "0x%016" PRIX64 "\n", cast_val_to_uint64(backbuffer_crc64));
8878 //----------------------------------------------------------------------------------------------------------------------
8879 // vogl_gl_replayer::is_valid_handle
8880 //----------------------------------------------------------------------------------------------------------------------
8881 bool vogl_gl_replayer::replay_to_trace_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
8888 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
8890 switch (handle_namespace)
8892 case VOGL_NAMESPACE_VERTEX_ARRAYS:
8894 VOGL_ASSERT(replay_handle32 == replay_handle);
8895 return (m_replayer.get_context_state()->m_vertex_array_objects.search_table_for_value_get_count(replay_handle32) != 0);
8897 case VOGL_NAMESPACE_FRAMEBUFFERS:
8899 VOGL_ASSERT(replay_handle32 == replay_handle);
8900 return (m_replayer.get_context_state()->m_framebuffers.search_table_for_value_get_count(replay_handle32) != 0);
8902 case VOGL_NAMESPACE_TEXTURES:
8904 VOGL_ASSERT(replay_handle32 == replay_handle);
8905 return (m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle32) != 0);
8907 case VOGL_NAMESPACE_RENDER_BUFFERS:
8909 VOGL_ASSERT(replay_handle32 == replay_handle);
8910 return (m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains_inv(replay_handle32) != 0);
8912 case VOGL_NAMESPACE_QUERIES:
8914 VOGL_ASSERT(replay_handle32 == replay_handle);
8915 return (m_replayer.get_shared_state()->m_queries.search_table_for_value_get_count(replay_handle32) != 0);
8917 case VOGL_NAMESPACE_SAMPLERS:
8919 VOGL_ASSERT(replay_handle32 == replay_handle);
8920 return (m_replayer.get_shared_state()->m_sampler_objects.search_table_for_value_get_count(replay_handle32) != 0);
8922 case VOGL_NAMESPACE_PROGRAMS:
8924 VOGL_ASSERT(replay_handle32 == replay_handle);
8925 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT;
8927 case VOGL_NAMESPACE_SHADERS:
8929 VOGL_ASSERT(replay_handle32 == replay_handle);
8930 return m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT;
8932 case VOGL_NAMESPACE_BUFFERS:
8934 VOGL_ASSERT(replay_handle32 == replay_handle);
8935 return m_replayer.get_shared_state()->m_buffers.search_table_for_value_get_count(replay_handle32);
8937 case VOGL_NAMESPACE_SYNCS:
8939 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
8940 return m_replayer.get_shared_state()->m_syncs.search_table_for_value_get_count(replay_sync) != 0;
8942 case VOGL_NAMESPACE_PROGRAM_ARB:
8944 VOGL_ASSERT(replay_handle32 == replay_handle);
8945 return m_replayer.get_shared_state()->m_arb_programs.search_table_for_value_get_count(replay_handle32) != 0;
8956 //----------------------------------------------------------------------------------------------------------------------
8957 // vogl_gl_replayer::remap_handle
8958 //----------------------------------------------------------------------------------------------------------------------
8959 uint64_t vogl_gl_replayer::replay_to_trace_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t replay_handle)
8966 uint32 replay_handle32 = static_cast<uint32>(replay_handle);
8968 switch (handle_namespace)
8970 case VOGL_NAMESPACE_VERTEX_ARRAYS:
8972 VOGL_ASSERT(replay_handle32 == replay_handle);
8973 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_vertex_array_objects, replay_handle32))
8974 return replay_handle32;
8977 case VOGL_NAMESPACE_FRAMEBUFFERS:
8979 VOGL_ASSERT(replay_handle32 == replay_handle);
8980 if (remap_replay_to_trace_handle(m_replayer.get_context_state()->m_framebuffers, replay_handle32))
8981 return replay_handle32;
8984 case VOGL_NAMESPACE_TEXTURES:
8986 VOGL_ASSERT(replay_handle32 == replay_handle);
8988 uint32 trace_handle = replay_handle32;
8989 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle32, trace_handle))
8990 return trace_handle;
8994 case VOGL_NAMESPACE_RENDER_BUFFERS:
8996 VOGL_ASSERT(replay_handle32 == replay_handle);
8997 GLuint trace_handle = replay_handle32;
8998 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_inv_handle_to_handle(replay_handle32, trace_handle))
8999 return trace_handle;
9003 case VOGL_NAMESPACE_QUERIES:
9005 VOGL_ASSERT(replay_handle32 == replay_handle);
9006 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_queries, replay_handle32))
9007 return replay_handle32;
9010 case VOGL_NAMESPACE_SAMPLERS:
9012 VOGL_ASSERT(replay_handle32 == replay_handle);
9013 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_sampler_objects, replay_handle32))
9014 return replay_handle32;
9017 case VOGL_NAMESPACE_PROGRAMS:
9019 VOGL_ASSERT(replay_handle32 == replay_handle);
9020 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_PROGRAM_OBJECT);
9021 GLuint trace_handle = replay_handle32;
9022 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9023 return trace_handle;
9026 case VOGL_NAMESPACE_SHADERS:
9028 VOGL_ASSERT(replay_handle32 == replay_handle);
9029 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle32) == VOGL_SHADER_OBJECT);
9030 GLuint trace_handle = replay_handle32;
9031 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle32, trace_handle))
9032 return trace_handle;
9035 case VOGL_NAMESPACE_BUFFERS:
9037 VOGL_ASSERT(replay_handle32 == replay_handle);
9038 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_buffers, replay_handle32))
9039 return replay_handle32;
9042 case VOGL_NAMESPACE_SYNCS:
9044 GLsync replay_sync = vogl_handle_to_sync(replay_handle);
9046 gl_sync_hash_map::const_iterator it(m_replayer.get_shared_state()->m_syncs.search_table_for_value(replay_sync));
9047 if (it != m_replayer.get_shared_state()->m_syncs.end())
9049 VOGL_ASSERT(it->second == replay_sync);
9055 case VOGL_NAMESPACE_PROGRAM_ARB:
9057 VOGL_ASSERT(replay_handle32 == replay_handle);
9058 if (remap_replay_to_trace_handle(m_replayer.get_shared_state()->m_arb_programs, replay_handle32))
9059 return replay_handle32;
9070 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));
9072 return replay_handle;
9075 //----------------------------------------------------------------------------------------------------------------------
9076 // vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location
9077 //----------------------------------------------------------------------------------------------------------------------
9078 int32 vogl_gl_replayer::replay_to_trace_handle_remapper::remap_location(uint32 replay_program, int32 replay_location)
9082 if ((!replay_program) || (replay_location < 0))
9083 return replay_location;
9085 GLuint trace_program = static_cast<GLuint>(remap_handle(VOGL_NAMESPACE_PROGRAMS, replay_program));
9087 glsl_program_hash_map::const_iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.find(trace_program));
9088 if (it != m_replayer.get_shared_state()->m_glsl_program_hash_map.end())
9090 const glsl_program_state &state = it->second;
9092 uniform_location_hash_map::const_iterator loc_it(state.m_uniform_locations.search_table_for_value(replay_location));
9093 if (loc_it != state.m_uniform_locations.end())
9094 return loc_it->first;
9097 vogl_warning_printf("%s: Failed remapping location %i of program %u\n", VOGL_METHOD_NAME, replay_location, replay_program);
9099 return replay_location;
9102 //----------------------------------------------------------------------------------------------------------------------
9103 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target
9104 //----------------------------------------------------------------------------------------------------------------------
9105 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9111 uint32 handle32 = static_cast<uint32>(replay_handle);
9113 switch (handle_namespace)
9115 case VOGL_NAMESPACE_TEXTURES:
9117 VOGL_ASSERT(handle32 == replay_handle);
9118 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9121 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9132 //----------------------------------------------------------------------------------------------------------------------
9133 // vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target
9134 //----------------------------------------------------------------------------------------------------------------------
9135 bool vogl_gl_replayer::replay_to_trace_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9141 uint32 handle32 = static_cast<uint32>(trace_handle);
9143 switch (handle_namespace)
9145 case VOGL_NAMESPACE_TEXTURES:
9147 VOGL_ASSERT(handle32 == trace_handle);
9148 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9151 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9162 //----------------------------------------------------------------------------------------------------------------------
9163 // vogl_replayer::determine_used_program_handles
9164 //----------------------------------------------------------------------------------------------------------------------
9165 bool vogl_gl_replayer::determine_used_program_handles(const vogl_trace_packet_array &trim_packets, vogl_handle_hash_set &replay_program_handles)
9169 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
9172 GLint cur_program_handle = 0;
9173 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &cur_program_handle);
9176 if (cur_program_handle)
9177 replay_program_handles.insert(cur_program_handle);
9180 // Scan for bound programs on all contexts in this sharegroup
9181 context_state *pContext_shareroot = m_pCur_context_state->m_pShared_state;
9182 for (context_hash_map::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it)
9184 context_state *pContext = it->second;
9185 if (pContext->m_pShared_state == pContext_shareroot)
9187 if (pContext->m_cur_replay_program)
9188 replay_program_handles.insert(pContext->m_cur_replay_program);
9192 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
9194 if (trim_packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
9197 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
9199 // 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.
9200 if (!m_temp2_gl_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
9203 GLuint trace_handle = 0;
9204 bool refers_to_program = vogl_does_packet_refer_to_program(m_temp2_gl_packet, trace_handle);
9205 if (!refers_to_program)
9210 // 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
9211 // 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).
9212 if (!trace_to_replay_remapper.is_valid_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle))
9215 uint64_t replay_handle = trace_to_replay_remapper.remap_handle(VOGL_NAMESPACE_PROGRAMS, trace_handle);
9219 VOGL_ASSERT(utils::is_32bit(replay_handle));
9221 replay_program_handles.insert(static_cast<uint32>(replay_handle));
9224 vogl_message_printf("%s: Found %u actually referenced program handles\n", VOGL_METHOD_NAME, replay_program_handles.size());
9229 //----------------------------------------------------------------------------------------------------------------------
9230 // vogl_replayer::fill_replay_handle_hash_set
9231 //----------------------------------------------------------------------------------------------------------------------
9232 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)
9236 replay_handle_hash.reset();
9237 replay_handle_hash.reserve(trace_to_replay_hash.size());
9238 for (gl_handle_hash_map::const_iterator it = trace_to_replay_hash.begin(); it != trace_to_replay_hash.end(); ++it)
9240 // Insert replay handles into destination hash table
9241 bool success = replay_handle_hash.insert(it->second).second;
9242 VOGL_ASSERT(success);
9243 VOGL_NOTE_UNUSED(success);
9247 //----------------------------------------------------------------------------------------------------------------------
9248 // vogl_replayer::snapshot_state
9249 //----------------------------------------------------------------------------------------------------------------------
9250 vogl_gl_state_snapshot *vogl_gl_replayer::snapshot_state(const vogl_trace_packet_array *pTrim_packets, bool optimize_snapshot)
9254 timed_scope ts(VOGL_METHOD_NAME);
9256 vogl_gl_state_snapshot *pSnapshot = vogl_new(vogl_gl_state_snapshot);
9258 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,
9259 m_pWindow->get_width(), m_pWindow->get_height(), m_cur_trace_context, m_frame_index, m_last_parsed_call_counter, m_at_frame_boundary);
9261 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))
9263 vogl_error_printf("%s: Failed beginning capture\n", VOGL_METHOD_NAME);
9265 vogl_delete(pSnapshot);
9271 vogl_client_side_array_desc_vec client_side_vertex_attrib_ptrs;
9272 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_vertex_attrib_data); i++)
9273 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()));
9275 vogl_client_side_array_desc_vec client_side_array_ptrs;
9276 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_array_data); i++)
9277 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()));
9279 vogl_client_side_array_desc_vec client_side_texcoord_ptrs;
9280 for (uint i = 0; i < VOGL_ARRAY_SIZE(m_client_side_texcoord_data); i++)
9281 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()));
9283 pSnapshot->add_client_side_array_ptrs(client_side_vertex_attrib_ptrs, client_side_array_ptrs, client_side_texcoord_ptrs);
9285 vogl_printf("%s: Capturing %u context(s)\n", VOGL_METHOD_NAME, m_contexts.size());
9287 context_hash_map::iterator it;
9288 for (it = m_contexts.begin(); it != m_contexts.end(); ++it)
9290 context_state *pContext_state = it->second;
9292 if (pContext_state->m_deleted)
9294 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));
9298 vogl_capture_context_params temp_shadow_state;
9299 vogl_capture_context_params *pShadow_state = &temp_shadow_state;
9301 if (pContext_state->m_has_been_made_current)
9303 status_t status = switch_contexts(it->first);
9304 if (status != cStatusOK)
9306 vogl_error_printf("%s: Failed switching to trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first));
9310 VOGL_ASSERT(m_pCur_context_state == pContext_state);
9312 if (m_pCur_context_state->m_inside_gl_begin)
9314 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));
9315 pSnapshot->set_is_restorable(false);
9318 if (get_shared_state()->m_mapped_buffers.size())
9320 vogl_warning_printf("%s: Trace context 0x%" PRIX64 " has %u currently mapped GL buffers, this scenario is not currently unsupported for state capturing. Capture will continue but will not be replayable.\n", VOGL_METHOD_NAME, cast_val_to_uint64(it->first), get_shared_state()->m_mapped_buffers.size());
9321 pSnapshot->set_is_restorable(false);
9324 // Init the shadow state needed by the snapshot code.
9325 if (!m_pCur_context_state->is_root_context())
9327 // Only fill in non-shared state.
9328 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9329 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9333 pShadow_state = &m_pCur_context_state->m_shadow_state;
9335 pShadow_state->m_query_targets = get_shared_state()->m_query_targets;
9337 fill_replay_handle_hash_set(pShadow_state->m_samplers, get_shared_state()->m_sampler_objects);
9338 fill_replay_handle_hash_set(pShadow_state->m_framebuffers, get_context_state()->m_framebuffers);
9339 fill_replay_handle_hash_set(pShadow_state->m_vaos, get_context_state()->m_vertex_array_objects);
9342 pShadow_state->m_buffer_targets.reset();
9343 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)
9345 GLuint trace_handle = buf_it->first;
9346 GLuint replay_handle = buf_it->second;
9348 gl_handle_hash_map::const_iterator target_it = get_shared_state()->m_buffer_targets.find(trace_handle);
9349 if (target_it == get_shared_state()->m_buffer_targets.end())
9351 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);
9354 GLenum target = target_it->second;
9356 pShadow_state->m_buffer_targets.insert(replay_handle, target);
9360 pShadow_state->m_syncs.reset();
9361 pShadow_state->m_syncs.reserve(get_shared_state()->m_syncs.size());
9362 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)
9364 bool success = pShadow_state->m_syncs.insert(vogl_sync_to_handle(sync_it->second)).second;
9365 VOGL_ASSERT(success);
9366 VOGL_NOTE_UNUSED(success);
9369 // Program handles filter
9370 pShadow_state->m_filter_program_handles = false;
9371 pShadow_state->m_program_handles_filter.reset();
9374 // 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).
9375 // This is an optimization issue, and we're concentrating on correctness right now so let's figure this out later.
9376 if ((pTrim_packets) && (optimize_snapshot))
9378 if (!determine_used_program_handles(*pTrim_packets, pShadow_state->m_program_handles_filter))
9380 vogl_warning_printf("%s: Failed determining used program handles\n", VOGL_METHOD_NAME);
9381 pShadow_state->m_program_handles_filter.clear();
9385 pShadow_state->m_filter_program_handles = true;
9389 VOGL_NOTE_UNUSED(optimize_snapshot);
9390 VOGL_NOTE_UNUSED(pTrim_packets);
9393 // ARB program targets
9394 pShadow_state->m_arb_program_targets.reset();
9395 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)
9397 GLuint trace_handle = arb_prog_it->first;
9398 GLuint replay_handle = get_shared_state()->m_arb_programs.value(trace_handle);
9399 if ((!trace_handle) || (!replay_handle))
9405 GLenum target = arb_prog_it->second;
9406 pShadow_state->m_arb_program_targets.insert(replay_handle, target);
9411 if (!pSnapshot->capture_context(pContext_state->m_context_desc, pContext_state->m_context_info, m_replay_to_trace_remapper, *pShadow_state))
9413 vogl_error_printf("%s: Failed capturing trace context 0x%" PRIX64 ", capture failed\n", VOGL_METHOD_NAME, static_cast<uint64_t>(it->first));
9418 if ((it == m_contexts.end()) && (pSnapshot->end_capture()))
9420 vogl_printf("%s: Capture succeeded\n", VOGL_METHOD_NAME);
9424 vogl_printf("%s: Capture failed\n", VOGL_METHOD_NAME);
9426 vogl_delete(pSnapshot);
9433 //----------------------------------------------------------------------------------------------------------------------
9434 // vogl_replayer::reset_state
9435 //----------------------------------------------------------------------------------------------------------------------
9436 void vogl_gl_replayer::reset_state()
9440 // Purposely does NOT destroy the cached snapshots
9442 destroy_pending_snapshot();
9445 m_pending_make_current_packet.clear();
9446 m_pending_window_resize_width = 0;
9447 m_pending_window_resize_height = 0;
9448 m_pending_window_resize_attempt_counter = 0;
9451 m_last_parsed_call_counter = -1;
9452 m_last_processed_call_counter = -1;
9453 m_at_frame_boundary = true;
9455 m_cur_trace_context = 0;
9456 m_cur_replay_context = 0;
9457 m_pCur_context_state = NULL;
9460 //if (m_pWindow->is_opened())
9461 // m_pWindow->clear_window();
9464 //----------------------------------------------------------------------------------------------------------------------
9465 // trace_to_replay_handle_remapper::is_valid_handle
9466 //----------------------------------------------------------------------------------------------------------------------
9467 bool vogl_gl_replayer::trace_to_replay_handle_remapper::is_valid_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9474 uint32 from_handle32 = static_cast<uint32>(from_handle);
9476 switch (handle_namespace)
9478 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9480 VOGL_ASSERT(from_handle32 == from_handle);
9481 return m_replayer.get_context_state()->m_vertex_array_objects.contains(from_handle32);
9483 case VOGL_NAMESPACE_TEXTURES:
9485 VOGL_ASSERT(from_handle32 == from_handle);
9486 return m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(from_handle32);
9488 case VOGL_NAMESPACE_SAMPLERS:
9490 VOGL_ASSERT(from_handle32 == from_handle);
9491 return m_replayer.get_shared_state()->m_sampler_objects.contains(from_handle32);
9493 case VOGL_NAMESPACE_BUFFERS:
9495 VOGL_ASSERT(from_handle32 == from_handle);
9496 return m_replayer.get_shared_state()->m_buffers.contains(from_handle32);
9498 case VOGL_NAMESPACE_SHADERS:
9499 case VOGL_NAMESPACE_PROGRAMS:
9501 VOGL_ASSERT(from_handle32 == from_handle);
9502 return m_replayer.get_shared_state()->m_shadow_state.m_objs.contains(from_handle32);
9504 case VOGL_NAMESPACE_FRAMEBUFFERS:
9506 VOGL_ASSERT(from_handle32 == from_handle);
9507 return m_replayer.get_context_state()->m_framebuffers.contains(from_handle32);
9509 case VOGL_NAMESPACE_RENDER_BUFFERS:
9511 VOGL_ASSERT(from_handle32 == from_handle);
9512 return m_replayer.get_shared_state()->m_shadow_state.m_rbos.contains(from_handle32);
9514 case VOGL_NAMESPACE_QUERIES:
9516 VOGL_ASSERT(from_handle32 == from_handle);
9517 return m_replayer.get_shared_state()->m_queries.contains(from_handle32);
9519 case VOGL_NAMESPACE_SYNCS:
9521 return m_replayer.get_shared_state()->m_syncs.contains(from_handle);
9523 case VOGL_NAMESPACE_PROGRAM_ARB:
9525 return m_replayer.get_shared_state()->m_arb_programs.contains(from_handle32);
9536 //----------------------------------------------------------------------------------------------------------------------
9537 // trace_to_replay_handle_remapper::remap_handle
9538 //----------------------------------------------------------------------------------------------------------------------
9539 uint64_t vogl_gl_replayer::trace_to_replay_handle_remapper::remap_handle(vogl_namespace_t handle_namespace, uint64_t from_handle)
9546 uint32 from_handle32 = static_cast<uint32>(from_handle);
9548 switch (handle_namespace)
9550 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9552 VOGL_ASSERT(from_handle32 == from_handle);
9553 return m_replayer.get_context_state()->m_vertex_array_objects.value(from_handle32, from_handle32);
9555 case VOGL_NAMESPACE_TEXTURES:
9557 VOGL_ASSERT(from_handle32 == from_handle);
9559 uint32 replay_handle = from_handle32;
9560 if (m_replayer.get_shared_state()->m_shadow_state.m_textures.map_handle_to_inv_handle(from_handle32, replay_handle))
9561 return replay_handle;
9564 case VOGL_NAMESPACE_SAMPLERS:
9566 VOGL_ASSERT(from_handle32 == from_handle);
9567 return m_replayer.get_shared_state()->m_sampler_objects.value(from_handle32, from_handle32);
9569 case VOGL_NAMESPACE_BUFFERS:
9571 VOGL_ASSERT(from_handle32 == from_handle);
9572 return m_replayer.get_shared_state()->m_buffers.value(from_handle32, from_handle32);
9574 case VOGL_NAMESPACE_SHADERS:
9575 case VOGL_NAMESPACE_PROGRAMS:
9577 VOGL_ASSERT(from_handle32 == from_handle);
9579 GLuint replay_handle = from_handle32;
9580 if (m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_handle32, replay_handle))
9581 return replay_handle;
9584 case VOGL_NAMESPACE_FRAMEBUFFERS:
9586 VOGL_ASSERT(from_handle32 == from_handle);
9587 return m_replayer.get_context_state()->m_framebuffers.value(from_handle32, from_handle32);
9589 case VOGL_NAMESPACE_RENDER_BUFFERS:
9591 VOGL_ASSERT(from_handle32 == from_handle);
9593 GLuint replay_handle = from_handle32;
9594 if (m_replayer.get_shared_state()->m_shadow_state.m_rbos.map_handle_to_inv_handle(from_handle32, replay_handle))
9595 return replay_handle;
9599 case VOGL_NAMESPACE_QUERIES:
9601 VOGL_ASSERT(from_handle32 == from_handle);
9602 return m_replayer.get_shared_state()->m_queries.value(from_handle32, from_handle32);
9604 case VOGL_NAMESPACE_SYNCS:
9606 return vogl_sync_to_handle(m_replayer.get_shared_state()->m_syncs.value(from_handle, vogl_handle_to_sync(from_handle)));
9608 case VOGL_NAMESPACE_PROGRAM_ARB:
9610 return m_replayer.get_shared_state()->m_arb_programs.value(from_handle32, from_handle32);
9620 vogl_error_printf("%s: Failed remapping handle %" PRIu64 " in namespace %s.\n", VOGL_METHOD_NAME, from_handle, vogl_get_namespace_name(handle_namespace));
9625 //----------------------------------------------------------------------------------------------------------------------
9626 // trace_to_replay_handle_remapper::remap_location
9627 //----------------------------------------------------------------------------------------------------------------------
9628 int32 vogl_gl_replayer::trace_to_replay_handle_remapper::remap_location(uint32 trace_program, int32 from_location)
9632 VOGL_NOTE_UNUSED(trace_program);
9634 // restoring declares, but doesn't need to remap
9637 return from_location;
9640 //----------------------------------------------------------------------------------------------------------------------
9641 // trace_to_replay_handle_remapper::remap_vertex_attrib_ptr
9642 //----------------------------------------------------------------------------------------------------------------------
9643 vogl_trace_ptr_value vogl_gl_replayer::trace_to_replay_handle_remapper::remap_vertex_attrib_ptr(uint index, vogl_trace_ptr_value ptr_val)
9650 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_vertex_attrib_data));
9651 if (!m_replayer.m_client_side_vertex_attrib_data[index].size())
9653 m_replayer.m_client_side_vertex_attrib_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9656 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_vertex_attrib_data[index].get_ptr());
9659 //----------------------------------------------------------------------------------------------------------------------
9660 // trace_to_replay_handle_remapper::remap_vertex_array_ptr
9661 //----------------------------------------------------------------------------------------------------------------------
9662 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)
9666 VOGL_ASSERT(id < VOGL_NUM_CLIENT_SIDE_ARRAY_DESCS);
9671 if (id == vogl_texcoord_pointer_array_id)
9673 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_texcoord_data));
9675 if (!m_replayer.m_client_side_texcoord_data[index].size())
9677 m_replayer.m_client_side_texcoord_data[index].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9680 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_texcoord_data[index].get_ptr());
9684 VOGL_ASSERT(index < VOGL_ARRAY_SIZE(m_replayer.m_client_side_array_data));
9686 if (!m_replayer.m_client_side_array_data[id].size())
9688 m_replayer.m_client_side_array_data[id].resize(VOGL_MAX_CLIENT_SIDE_VERTEX_ARRAY_SIZE);
9691 return reinterpret_cast<vogl_trace_ptr_value>(m_replayer.m_client_side_array_data[id].get_ptr());
9695 //----------------------------------------------------------------------------------------------------------------------
9696 // trace_to_replay_handle_remapper::declare_handle
9697 //----------------------------------------------------------------------------------------------------------------------
9698 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)
9702 if ((!from_handle) || (!to_handle))
9708 uint32 from_handle32 = static_cast<uint32>(from_handle);
9709 uint32 to_handle32 = static_cast<uint32>(to_handle);
9711 switch (handle_namespace)
9713 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9715 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9716 m_replayer.get_context_state()->m_vertex_array_objects.insert(from_handle32, to_handle32);
9719 case VOGL_NAMESPACE_TEXTURES:
9721 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9722 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.update(from_handle32, to_handle32, target))
9723 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);
9726 case VOGL_NAMESPACE_SAMPLERS:
9728 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9729 m_replayer.get_shared_state()->m_sampler_objects.insert(from_handle32, to_handle32);
9732 case VOGL_NAMESPACE_BUFFERS:
9734 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9735 m_replayer.get_shared_state()->m_buffers.insert(from_handle32, to_handle32);
9736 m_replayer.get_shared_state()->m_buffer_targets.insert(from_handle32, target);
9739 case VOGL_NAMESPACE_SHADERS:
9741 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9742 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_SHADER_OBJECT))
9743 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);
9746 case VOGL_NAMESPACE_PROGRAMS:
9748 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9749 if (!m_replayer.get_shared_state()->m_shadow_state.m_objs.insert(from_handle32, to_handle32, VOGL_PROGRAM_OBJECT))
9750 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);
9753 case VOGL_NAMESPACE_FRAMEBUFFERS:
9755 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9756 m_replayer.get_context_state()->m_framebuffers.insert(from_handle32, to_handle32);
9759 case VOGL_NAMESPACE_RENDER_BUFFERS:
9761 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9762 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.insert(from_handle32, to_handle32, GL_NONE))
9763 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);
9766 case VOGL_NAMESPACE_QUERIES:
9768 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9769 m_replayer.get_shared_state()->m_queries.insert(from_handle32, to_handle32);
9770 m_replayer.get_shared_state()->m_query_targets[to_handle32] = target;
9773 case VOGL_NAMESPACE_SYNCS:
9775 m_replayer.get_shared_state()->m_syncs.insert(from_handle, vogl_handle_to_sync(to_handle));
9778 case VOGL_NAMESPACE_PROGRAM_ARB:
9780 m_replayer.get_shared_state()->m_arb_programs.insert(from_handle32, to_handle32);
9781 m_replayer.get_shared_state()->m_arb_program_targets.insert(from_handle32, target);
9792 //----------------------------------------------------------------------------------------------------------------------
9793 // trace_to_replay_handle_remapper::delete_handle_and_object
9794 //----------------------------------------------------------------------------------------------------------------------
9795 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)
9799 if ((!from_handle) || (!to_handle))
9805 uint32 from_handle32 = static_cast<uint32>(from_handle);
9806 uint32 to_handle32 = static_cast<uint32>(to_handle);
9807 VOGL_NOTE_UNUSED(to_handle32);
9809 switch (handle_namespace)
9811 case VOGL_NAMESPACE_VERTEX_ARRAYS:
9813 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9814 m_replayer.get_context_state()->m_vertex_array_objects.erase(from_handle32);
9815 vogl_destroy_gl_object(handle_namespace, to_handle);
9818 case VOGL_NAMESPACE_TEXTURES:
9820 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9821 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.erase(from_handle32))
9822 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);
9824 vogl_destroy_gl_object(handle_namespace, to_handle);
9827 case VOGL_NAMESPACE_SAMPLERS:
9829 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9830 m_replayer.get_shared_state()->m_sampler_objects.erase(from_handle32);
9831 vogl_destroy_gl_object(handle_namespace, to_handle);
9834 case VOGL_NAMESPACE_BUFFERS:
9836 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9837 m_replayer.get_shared_state()->m_buffers.erase(from_handle32);
9838 m_replayer.get_shared_state()->m_buffer_targets.erase(from_handle32);
9839 vogl_destroy_gl_object(handle_namespace, to_handle);
9842 case VOGL_NAMESPACE_SHADERS:
9844 m_replayer.handle_delete_shader(from_handle32);
9847 case VOGL_NAMESPACE_PROGRAMS:
9849 m_replayer.handle_delete_program(from_handle32);
9852 case VOGL_NAMESPACE_FRAMEBUFFERS:
9854 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9855 m_replayer.get_context_state()->m_framebuffers.erase(from_handle32);
9856 vogl_destroy_gl_object(handle_namespace, to_handle);
9859 case VOGL_NAMESPACE_RENDER_BUFFERS:
9861 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9863 if (!m_replayer.get_shared_state()->m_shadow_state.m_rbos.erase(from_handle32))
9864 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);
9866 vogl_destroy_gl_object(handle_namespace, to_handle);
9869 case VOGL_NAMESPACE_QUERIES:
9871 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9872 m_replayer.get_shared_state()->m_queries.erase(from_handle32);
9873 vogl_destroy_gl_object(handle_namespace, to_handle);
9876 case VOGL_NAMESPACE_SYNCS:
9878 m_replayer.get_shared_state()->m_syncs.erase(from_handle);
9879 vogl_destroy_gl_object(handle_namespace, to_handle);
9882 case VOGL_NAMESPACE_PROGRAM_ARB:
9884 VOGL_ASSERT((from_handle32 == from_handle) && (to_handle32 == to_handle));
9885 m_replayer.get_shared_state()->m_arb_programs.erase(from_handle32);
9886 m_replayer.get_shared_state()->m_arb_program_targets.erase(from_handle32);
9887 vogl_destroy_gl_object(handle_namespace, to_handle);
9898 //----------------------------------------------------------------------------------------------------------------------
9899 // vogl_replayer::trace_to_replay_handle_remapper::declare_location
9900 //----------------------------------------------------------------------------------------------------------------------
9901 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)
9905 GLuint check_replay_handle = 0;
9906 VOGL_ASSERT(m_replayer.get_shared_state()->m_shadow_state.m_objs.map_handle_to_inv_handle(from_program_handle, check_replay_handle));
9907 VOGL_ASSERT(check_replay_handle == to_program_handle);
9908 VOGL_NOTE_UNUSED(check_replay_handle);
9910 VOGL_NOTE_UNUSED(to_program_handle);
9912 glsl_program_hash_map::iterator it(m_replayer.get_shared_state()->m_glsl_program_hash_map.insert(from_program_handle).first);
9914 glsl_program_state &prog_state = it->second;
9916 VOGL_ASSERT(!prog_state.m_uniform_locations.contains(from_location));
9918 prog_state.m_uniform_locations.insert(from_location, to_location);
9921 //----------------------------------------------------------------------------------------------------------------------
9922 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target
9923 //----------------------------------------------------------------------------------------------------------------------
9924 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_from_object_target(vogl_namespace_t handle_namespace, uint64_t trace_handle, GLenum &target)
9930 uint32 handle32 = static_cast<uint32>(trace_handle);
9932 switch (handle_namespace)
9934 case VOGL_NAMESPACE_TEXTURES:
9936 VOGL_ASSERT(handle32 == trace_handle);
9937 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains(handle32))
9940 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target(handle32);
9951 //----------------------------------------------------------------------------------------------------------------------
9952 // vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target
9953 //----------------------------------------------------------------------------------------------------------------------
9954 bool vogl_gl_replayer::trace_to_replay_handle_remapper::determine_to_object_target(vogl_namespace_t handle_namespace, uint64_t replay_handle, GLenum &target)
9960 uint32 handle32 = static_cast<uint32>(replay_handle);
9962 switch (handle_namespace)
9964 case VOGL_NAMESPACE_TEXTURES:
9966 VOGL_ASSERT(handle32 == replay_handle);
9967 if (!m_replayer.get_shared_state()->m_shadow_state.m_textures.contains_inv(handle32))
9970 target = m_replayer.get_shared_state()->m_shadow_state.m_textures.get_target_inv(handle32);
9981 //----------------------------------------------------------------------------------------------------------------------
9982 // vogl_replayer::restore_objects
9983 //----------------------------------------------------------------------------------------------------------------------
9984 vogl_gl_replayer::status_t vogl_gl_replayer::restore_objects(
9985 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,
9986 vogl_const_gl_object_state_ptr_vec &objects_to_delete)
9990 VOGL_NOTE_UNUSED(snapshot);
9992 if (m_flags & cGLReplayerVerboseMode)
9993 vogl_printf("%s: Restoring %s objects\n", VOGL_METHOD_NAME, get_gl_object_state_type_str(state_type));
9996 if (m_flags & cGLReplayerVerboseMode)
9999 const vogl_gl_object_state_ptr_vec &object_ptrs = context_state.get_objects();
10003 for (uint i = 0; i < object_ptrs.size(); i++)
10005 const vogl_gl_object_state *pState_obj = object_ptrs[i];
10007 if (pState_obj->get_type() != state_type)
10010 GLuint64 restore_handle = 0;
10011 if (!pState_obj->restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, restore_handle))
10013 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);
10014 return cStatusHardFailure;
10018 if (pState_obj->get_marked_for_deletion())
10020 objects_to_delete.push_back(pState_obj);
10023 VOGL_ASSERT(trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle()) == restore_handle);
10025 switch (pState_obj->get_type())
10029 const vogl_query_state *pQuery = static_cast<const vogl_query_state *>(pState_obj);
10031 VOGL_ASSERT(restore_handle <= cUINT32_MAX);
10032 get_shared_state()->m_query_targets[static_cast<GLuint>(restore_handle)] = pQuery->get_target();
10038 const vogl_program_state *pProg = static_cast<const vogl_program_state *>(pState_obj);
10040 if (pProg->has_link_time_snapshot())
10042 vogl_program_state link_snapshot(*pProg->get_link_time_snapshot());
10043 if (!link_snapshot.remap_handles(trace_to_replay_remapper))
10045 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);
10049 get_shared_state()->m_shadow_state.m_linked_programs.add_snapshot(static_cast<uint32>(restore_handle), link_snapshot);
10053 if (m_flags & cGLReplayerVerboseMode)
10055 if ((n & 255) == 255)
10056 vogl_printf("%s: Restored %u programs\n", VOGL_METHOD_NAME, n);
10066 if (m_flags & cGLReplayerVerboseMode)
10069 vogl_printf("%s: Restore took %f secs\n", VOGL_METHOD_NAME, tm.get_elapsed_secs());
10071 vogl_printf("%s: Finished restoring %u %s objects\n", VOGL_METHOD_NAME, n, get_gl_object_state_type_str(state_type));
10077 //----------------------------------------------------------------------------------------------------------------------
10078 // vogl_xfont_cache
10079 //----------------------------------------------------------------------------------------------------------------------
10080 class vogl_xfont_cache
10082 VOGL_NO_COPY_OR_ASSIGNMENT_OP(vogl_xfont_cache);
10085 vogl_xfont_cache(Display *dpy)
10091 ~vogl_xfont_cache()
10102 for (xfont_map::iterator it = m_xfonts.begin(); it != m_xfonts.end(); ++it)
10103 XFreeFont(m_dpy, it->second);
10107 XFontStruct *get_or_create(const char *pName)
10111 XFontStruct **ppXFont = m_xfonts.find_value(pName);
10115 XFontStruct *pXFont = XLoadQueryFont(m_dpy, pName);
10117 m_xfonts.insert(pName, pXFont);
10125 typedef vogl::map<dynamic_string, XFontStruct *> xfont_map;
10126 xfont_map m_xfonts;
10129 //----------------------------------------------------------------------------------------------------------------------
10130 // vogl_replayer::restore_display_lists
10131 //----------------------------------------------------------------------------------------------------------------------
10132 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)
10136 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10137 VOGL_NOTE_UNUSED(snapshot);
10139 VOGL_ASSERT(m_cur_trace_context);
10143 const vogl_display_list_state &disp_lists = context_snapshot.get_display_list_state();
10145 if (!disp_lists.size())
10148 vogl_message_printf("%s: Recreating %u display lists\n", VOGL_METHOD_NAME, disp_lists.get_display_list_map().size());
10150 vogl_xfont_cache xfont_cache(m_pWindow->get_display());
10152 const vogl_display_list_map &disp_list_map = disp_lists.get_display_list_map();
10154 for (vogl_display_list_map::const_iterator it = disp_list_map.begin(); it != disp_list_map.end(); ++it)
10156 GLuint trace_handle = it->first;
10157 const vogl_display_list &disp_list = it->second;
10161 VOGL_ASSERT_ALWAYS;
10165 if (!disp_list.is_valid())
10167 VOGL_ASSERT_ALWAYS;
10171 GLuint replay_handle = GL_ENTRYPOINT(glGenLists)(1);
10172 if (check_gl_error() || !replay_handle)
10173 goto handle_failure;
10175 if (disp_list.is_xfont())
10177 XFontStruct *pXFont = xfont_cache.get_or_create(disp_list.get_xfont_name().get_ptr());
10180 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);
10184 GL_ENTRYPOINT(glXUseXFont)(pXFont->fid, disp_list.get_xfont_glyph(), 1, replay_handle);
10189 GL_ENTRYPOINT(glNewList)(replay_handle, GL_COMPILE);
10191 if (check_gl_error() || !replay_handle)
10193 GL_ENTRYPOINT(glDeleteLists)(replay_handle, 1);
10196 goto handle_failure;
10199 const vogl_trace_packet_array &packets = disp_list.get_packets();
10201 for (uint packet_index = 0; packet_index < packets.size(); packet_index++)
10203 if (packets.get_packet_type(packet_index) != cTSPTGLEntrypoint)
10205 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);
10209 const uint8_vec &packet_buf = packets.get_packet_buf(packet_index);
10211 if (!m_temp2_gl_packet.deserialize(packet_buf, true))
10213 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);
10217 vogl_trace_gl_entrypoint_packet &gl_entrypoint_packet = m_temp2_gl_packet.get_entrypoint_packet();
10219 gl_entrypoint_packet.m_context_handle = m_cur_trace_context;
10221 if (m_flags & cGLReplayerDebugMode)
10222 dump_trace_gl_packet_debug_info(gl_entrypoint_packet);
10224 int64_t prev_parsed_call_counter = m_last_parsed_call_counter;
10225 int64_t prev_processed_call_counter = m_last_processed_call_counter;
10226 m_last_parsed_call_counter = gl_entrypoint_packet.m_call_counter;
10227 m_last_processed_call_counter = gl_entrypoint_packet.m_call_counter;
10228 bool prev_at_frame_boundary = m_at_frame_boundary;
10230 const vogl_trace_packet *pPrev_gl_packet = m_pCur_gl_packet;
10232 vogl_gl_replayer::status_t status = process_gl_entrypoint_packet_internal(m_temp2_gl_packet);
10234 m_pCur_gl_packet = pPrev_gl_packet;
10236 m_last_parsed_call_counter = prev_parsed_call_counter;
10237 m_last_processed_call_counter = prev_processed_call_counter;
10238 m_at_frame_boundary = prev_at_frame_boundary;
10240 if (status != cStatusOK)
10242 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);
10247 // TODO: Set context state because we're currently generating a display list!
10248 if (disp_list.is_generating())
10250 VOGL_ASSERT_ALWAYS;
10253 GL_ENTRYPOINT(glEndList)();
10257 get_shared_state()->m_lists.insert(trace_handle, replay_handle);
10259 if (!get_shared_state()->m_shadow_state.m_display_lists.define_list(trace_handle, replay_handle, disp_list))
10261 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);
10267 vogl_message_printf("%s: Done recreating display lists\n", VOGL_METHOD_NAME);
10272 return cStatusHardFailure;
10275 //----------------------------------------------------------------------------------------------------------------------
10276 // vogl_replayer::restore_general_state
10277 //----------------------------------------------------------------------------------------------------------------------
10278 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)
10282 VOGL_NOTE_UNUSED(snapshot);
10284 vogl_general_context_state::vogl_persistent_restore_state persistent_restore_state;
10285 persistent_restore_state.m_pSelect_buffer = &m_pCur_context_state->m_select_buffer;
10287 if (!context_snapshot.get_general_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper, persistent_restore_state))
10288 return cStatusHardFailure;
10290 if (!m_pCur_context_state->m_context_info.is_core_profile())
10292 if (context_snapshot.get_texenv_state().is_valid())
10294 if (!context_snapshot.get_texenv_state().restore(m_pCur_context_state->m_context_info))
10295 return cStatusHardFailure;
10298 if (context_snapshot.get_material_state().is_valid())
10300 if (!context_snapshot.get_material_state().restore(m_pCur_context_state->m_context_info))
10301 return cStatusHardFailure;
10304 if (context_snapshot.get_light_state().is_valid())
10306 if (!context_snapshot.get_light_state().restore(m_pCur_context_state->m_context_info))
10307 return cStatusHardFailure;
10310 if (context_snapshot.get_matrix_state().is_valid())
10312 if (!context_snapshot.get_matrix_state().restore(m_pCur_context_state->m_context_info))
10313 return cStatusHardFailure;
10316 if (context_snapshot.get_polygon_stipple_state().is_valid())
10318 if (!context_snapshot.get_polygon_stipple_state().restore(m_pCur_context_state->m_context_info))
10319 return cStatusHardFailure;
10322 if (context_snapshot.get_arb_program_environment_state().is_valid())
10324 if (m_pCur_context_state->m_context_info.supports_extension("GL_ARB_vertex_program"))
10326 if (!context_snapshot.get_arb_program_environment_state().restore(m_pCur_context_state->m_context_info, trace_to_replay_remapper))
10327 return cStatusHardFailure;
10331 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);
10336 if (context_snapshot.get_current_vertex_attrib_state().is_valid())
10338 if (!context_snapshot.get_current_vertex_attrib_state().restore(m_pCur_context_state->m_context_info))
10339 return cStatusHardFailure;
10345 //----------------------------------------------------------------------------------------------------------------------
10346 // vogl_replayer::validate_program_and_shader_handle_tables
10347 //----------------------------------------------------------------------------------------------------------------------
10348 bool vogl_gl_replayer::validate_program_and_shader_handle_tables()
10352 if (!m_pCur_context_state)
10355 if (!get_shared_state()->m_shadow_state.m_objs.check())
10356 vogl_error_printf("%s: Object handle tracker failed validation!\n", VOGL_METHOD_NAME);
10358 uint_vec replay_handles;
10359 get_shared_state()->m_shadow_state.m_objs.get_inv_handles(replay_handles);
10361 for (uint i = 0; i < replay_handles.size(); i++)
10363 GLuint replay_handle = replay_handles[i];
10364 GLuint trace_handle = replay_handle;
10365 bool map_succeeded = get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(replay_handle, trace_handle);
10366 VOGL_ASSERT(map_succeeded);
10367 VOGL_NOTE_UNUSED(map_succeeded);
10369 GLenum target = get_shared_state()->m_shadow_state.m_objs.get_target_inv(replay_handle);
10370 VOGL_ASSERT(target == get_shared_state()->m_shadow_state.m_objs.get_target(trace_handle));
10372 if (target == VOGL_PROGRAM_OBJECT)
10374 if (!GL_ENTRYPOINT(glIsProgram)(replay_handle))
10376 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);
10379 if (!get_shared_state()->m_glsl_program_hash_map.contains(trace_handle))
10381 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);
10384 else if (target == VOGL_SHADER_OBJECT)
10386 if (!GL_ENTRYPOINT(glIsShader)(replay_handle))
10388 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);
10393 VOGL_ASSERT_ALWAYS;
10400 //----------------------------------------------------------------------------------------------------------------------
10401 // vogl_replayer::validate_textures
10402 //----------------------------------------------------------------------------------------------------------------------
10403 bool vogl_gl_replayer::validate_textures()
10407 if (!m_pCur_context_state)
10410 if (!get_shared_state()->m_shadow_state.m_textures.check())
10411 vogl_error_printf("%s: Texture handle tracker failed validation!\n", VOGL_METHOD_NAME);
10413 for (uint replay_handle = 1; replay_handle <= 0xFFFFU; replay_handle++)
10415 bool is_tex = GL_ENTRYPOINT(glIsTexture)(replay_handle) != 0;
10417 bool found_in_shadow = get_shared_state()->m_shadow_state.m_textures.contains_inv(replay_handle);
10421 if (found_in_shadow)
10423 GLuint trace_handle = 0;
10424 get_shared_state()->m_shadow_state.m_textures.map_inv_handle_to_handle(replay_handle, trace_handle);
10425 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);
10430 if (!found_in_shadow)
10432 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);
10440 //----------------------------------------------------------------------------------------------------------------------
10441 // vogl_replayer::update_context_shadows
10442 //----------------------------------------------------------------------------------------------------------------------
10443 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)
10447 VOGL_NOTE_UNUSED(snapshot);
10448 VOGL_NOTE_UNUSED(context_snapshot);
10449 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10453 // Make sure shadow is good
10454 GLint actual_current_replay_program = 0;
10455 GL_ENTRYPOINT(glGetIntegerv)(GL_CURRENT_PROGRAM, &actual_current_replay_program);
10458 m_pCur_context_state->m_cur_replay_program = actual_current_replay_program;
10459 if (!actual_current_replay_program)
10460 m_pCur_context_state->m_cur_trace_program = 0;
10463 GLuint trace_handle = actual_current_replay_program;
10464 if (!get_shared_state()->m_shadow_state.m_objs.map_inv_handle_to_handle(actual_current_replay_program, trace_handle))
10466 process_entrypoint_error("%s: Failed finding restored GL shader %u in program/shader object handle hashmap\n", VOGL_METHOD_NAME, actual_current_replay_program);
10468 m_pCur_context_state->m_cur_replay_program = 0;
10469 m_pCur_context_state->m_cur_trace_program = 0;
10473 m_pCur_context_state->m_cur_trace_program = trace_handle;
10477 check_program_binding_shadow();
10482 //----------------------------------------------------------------------------------------------------------------------
10483 // vogl_replayer::handle_marked_for_deleted_objects
10484 //----------------------------------------------------------------------------------------------------------------------
10485 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)
10489 if (m_flags & cGLReplayerVerboseMode)
10491 vogl_debug_printf("%s: %u program/shader objects where marked as deleted\n", VOGL_METHOD_NAME, objects_to_delete.size());
10494 for (uint i = 0; i < objects_to_delete.size(); i++)
10496 const vogl_gl_object_state *pState_obj = objects_to_delete[i];
10498 GLuint64 trace_handle = pState_obj->get_snapshot_handle();
10499 GLuint64 restore_handle = trace_to_replay_remapper.remap_handle(pState_obj->get_handle_namespace(), pState_obj->get_snapshot_handle());
10501 if (m_flags & cGLReplayerVerboseMode)
10503 // This should be a rare/exception case so let's try to be a little paranoid.
10504 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,
10505 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10508 GLboolean object_is_still_a_name = true;
10510 switch (pState_obj->get_type())
10514 handle_delete_program(static_cast<GLuint>(trace_handle));
10516 object_is_still_a_name = GL_ENTRYPOINT(glIsProgram)(static_cast<GLuint>(restore_handle));
10522 handle_delete_shader(static_cast<GLuint>(trace_handle));
10524 object_is_still_a_name = GL_ENTRYPOINT(glIsShader)(static_cast<GLuint>(restore_handle));
10530 VOGL_ASSERT_ALWAYS;
10535 // "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."
10536 // Same for shaders.
10537 if (!object_is_still_a_name)
10539 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,
10540 get_gl_object_state_type_str(pState_obj->get_type()), (uint64_t)trace_handle, (uint64_t)restore_handle);
10545 //----------------------------------------------------------------------------------------------------------------------
10546 // vogl_replayer::begin_applying_snapshot
10547 // Takes ownership (even on errors) when delete_snapshot_after_applying is true.
10548 //----------------------------------------------------------------------------------------------------------------------
10549 vogl_gl_replayer::status_t vogl_gl_replayer::begin_applying_snapshot(const vogl_gl_state_snapshot *pSnapshot, bool delete_snapshot_after_applying)
10553 if (!pSnapshot->is_valid())
10555 if (delete_snapshot_after_applying)
10556 vogl_delete(const_cast<vogl_gl_state_snapshot *>(pSnapshot));
10558 return cStatusHardFailure;
10563 m_pPending_snapshot = pSnapshot;
10564 m_delete_pending_snapshot_after_applying = delete_snapshot_after_applying;
10566 m_frame_index = pSnapshot->get_frame_index();
10567 m_last_parsed_call_counter = pSnapshot->get_gl_call_counter();
10568 m_last_processed_call_counter = pSnapshot->get_gl_call_counter();
10569 m_at_frame_boundary = false;
10571 if (!(m_flags & cGLReplayerLockWindowDimensions))
10573 return trigger_pending_window_resize(pSnapshot->get_window_width(), pSnapshot->get_window_height());
10576 return process_applying_pending_snapshot();
10579 //----------------------------------------------------------------------------------------------------------------------
10580 // vogl_replayer::restore_context
10581 //----------------------------------------------------------------------------------------------------------------------
10582 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)
10586 VOGL_NOTE_UNUSED(trace_to_replay_remapper);
10587 VOGL_NOTE_UNUSED(snapshot);
10589 // TODO: This always creates with attribs, also need to support plain glXCreateContext()
10591 Display *dpy = m_pWindow->get_display();
10592 GLXFBConfig fb_config = m_pWindow->get_fb_configs()[0];
10594 vogl_trace_context_ptr_value trace_share_context = context_snapshot.get_context_desc().get_trace_share_context();
10596 GLXContext replay_share_context = remap_context(trace_share_context);
10597 if ((trace_share_context) && (!replay_share_context))
10599 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));
10600 return cStatusHardFailure;
10603 GLboolean direct = context_snapshot.get_context_desc().get_direct();
10605 vogl_trace_context_ptr_value trace_context = context_snapshot.get_context_desc().get_trace_context();
10607 status_t status = create_context_attribs(trace_context, dpy, fb_config, trace_share_context, replay_share_context, direct,
10608 context_snapshot.get_context_desc().get_attribs().get_vec().get_ptr(),
10609 context_snapshot.get_context_desc().get_attribs().get_vec().size(), true);
10610 if (status != cStatusOK)
10612 vogl_error_printf("%s: Failed creating new context\n", VOGL_METHOD_NAME);
10616 // Has this context ever been made current?
10617 if (context_snapshot.get_context_info().is_valid())
10619 context_state *pContext_state = get_trace_context_state(trace_context);
10620 if (!pContext_state)
10622 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
10623 return cStatusHardFailure;
10626 GLXContext replay_context = pContext_state->m_replay_context;
10627 if (!replay_context)
10629 vogl_error_printf("%s: Failed finding replay context current\n", VOGL_METHOD_NAME);
10630 return cStatusHardFailure;
10633 GLXDrawable drawable = m_pWindow->get_xwindow();
10635 Bool result = GL_ENTRYPOINT(glXMakeCurrent)(dpy, drawable, replay_context);
10638 vogl_error_printf("%s: Failed making context current\n", VOGL_METHOD_NAME);
10639 return cStatusHardFailure;
10642 m_cur_trace_context = trace_context;
10643 m_cur_replay_context = replay_context;
10644 m_pCur_context_state = pContext_state;
10646 if (!handle_context_made_current())
10647 return cStatusHardFailure;
10653 //----------------------------------------------------------------------------------------------------------------------
10654 // vogl_replayer::process_applying_pending_snapshot
10655 //----------------------------------------------------------------------------------------------------------------------
10656 vogl_gl_replayer::status_t vogl_gl_replayer::process_applying_pending_snapshot()
10660 if (!m_pPending_snapshot)
10663 timed_scope ts(VOGL_METHOD_NAME);
10665 const vogl_gl_state_snapshot &snapshot = *m_pPending_snapshot;
10667 trace_to_replay_handle_remapper trace_to_replay_remapper(*this);
10669 m_frame_index = snapshot.get_frame_index();
10670 m_last_parsed_call_counter = snapshot.get_gl_call_counter();
10671 m_last_processed_call_counter = snapshot.get_gl_call_counter();
10672 m_at_frame_boundary = snapshot.get_at_frame_boundary();
10674 // Ensure the client side array bufs are large enough (we don't care about the actual ptr values).
10675 for (uint i = 0; i < snapshot.get_client_side_vertex_attrib_ptrs().size(); i++)
10676 m_client_side_vertex_attrib_data[i].resize(snapshot.get_client_side_vertex_attrib_ptrs()[i].m_size);
10678 for (uint i = 0; i < snapshot.get_client_side_array_ptrs().size(); i++)
10679 m_client_side_array_data[i].resize(snapshot.get_client_side_array_ptrs()[i].m_size);
10681 for (uint i = 0; i < snapshot.get_client_side_texcoord_ptrs().size(); i++)
10682 m_client_side_texcoord_data[i].resize(snapshot.get_client_side_texcoord_ptrs()[i].m_size);
10684 const vogl_context_snapshot_ptr_vec &context_ptrs = snapshot.get_contexts();
10686 vogl_context_snapshot_ptr_vec restore_context_ptrs(snapshot.get_contexts());
10687 vogl::vector<vogl_const_gl_object_state_ptr_vec> objects_to_delete_vec(context_ptrs.size());
10689 status_t status = cStatusOK;
10690 uint total_contexts_restored = 0;
10691 bool restored_default_framebuffer = false;
10695 uint num_contexts_restored_in_this_pass = 0;
10697 for (uint context_index = 0; context_index < restore_context_ptrs.size(); context_index++)
10699 if (!restore_context_ptrs[context_index])
10702 const vogl_context_snapshot &context_state = *restore_context_ptrs[context_index];
10704 if (context_state.get_context_desc().get_trace_share_context())
10706 // Don't restore this context if its sharelist context hasn't been restored yet
10707 if (!remap_context(context_state.get_context_desc().get_trace_share_context()))
10711 status = restore_context(trace_to_replay_remapper, snapshot, context_state);
10712 if (status != cStatusOK)
10715 // Has this context ever been made current?
10716 if (context_state.get_context_info().is_valid())
10718 // 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!)
10719 const vogl_gl_object_state_type s_object_type_restore_order[] = { cGLSTBuffer, cGLSTSampler, cGLSTQuery, cGLSTRenderbuffer, cGLSTTexture, cGLSTFramebuffer, cGLSTVertexArray, cGLSTShader, cGLSTProgram, cGLSTSync, cGLSTARBProgram };
10720 VOGL_ASSUME(VOGL_ARRAY_SIZE(s_object_type_restore_order) == (cGLSTTotalTypes - 1));
10722 if (m_flags & cGLReplayerLowLevelDebugMode)
10724 if (!validate_textures())
10725 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
10728 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
10730 for (uint i = 0; i < VOGL_ARRAY_SIZE(s_object_type_restore_order); i++)
10732 status = restore_objects(trace_to_replay_remapper, snapshot, context_state, s_object_type_restore_order[i], objects_to_delete);
10733 if (status != cStatusOK)
10736 if (m_flags & cGLReplayerLowLevelDebugMode)
10738 if (!validate_program_and_shader_handle_tables())
10739 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
10741 if (!validate_textures())
10742 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
10746 if (m_flags & cGLReplayerLowLevelDebugMode)
10748 if (!validate_textures())
10749 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
10752 status = restore_display_lists(trace_to_replay_remapper, snapshot, context_state);
10753 if (status != cStatusOK)
10756 // Restore default framebuffer
10757 if ((!restored_default_framebuffer) && (snapshot.get_default_framebuffer().is_valid()))
10759 restored_default_framebuffer = true;
10761 if (!snapshot.get_default_framebuffer().restore(m_pCur_context_state->m_context_info))
10763 vogl_warning_printf("%s: Failed restoring default framebuffer!\n", VOGL_METHOD_NAME);
10767 // Beware: restore_general_state() will bind a bunch of stuff from the trace!
10768 status = restore_general_state(trace_to_replay_remapper, snapshot, context_state);
10769 if (status != cStatusOK)
10772 status = update_context_shadows(trace_to_replay_remapper, snapshot, context_state);
10773 if (status != cStatusOK)
10776 if (m_flags & cGLReplayerLowLevelDebugMode)
10778 if (!validate_program_and_shader_handle_tables())
10779 vogl_error_printf("%s: Program/shader handle table validation failed!\n", VOGL_METHOD_NAME);
10781 if (!validate_textures())
10782 vogl_warning_printf("%s: Failed validating texture handles against handle mapping tables\n", VOGL_METHOD_NAME);
10786 num_contexts_restored_in_this_pass++;
10788 total_contexts_restored++;
10790 restore_context_ptrs[context_index] = NULL;
10793 if (!num_contexts_restored_in_this_pass)
10797 if (total_contexts_restored != snapshot.get_contexts().size())
10799 vogl_error_printf("%s: Failed satisfying sharelist dependency during context restoration\n", VOGL_METHOD_NAME);
10803 for (uint context_index = 0; context_index < context_ptrs.size(); context_index++)
10805 const vogl_context_snapshot &context_state = *context_ptrs[context_index];
10807 if (!context_state.get_context_info().is_valid())
10810 status_t status = switch_contexts(context_state.get_context_desc().get_trace_context());
10811 if (status != cStatusOK)
10813 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()));
10817 vogl_const_gl_object_state_ptr_vec &objects_to_delete = objects_to_delete_vec[context_index];
10819 handle_marked_for_deleted_objects(objects_to_delete, trace_to_replay_remapper);
10822 destroy_pending_snapshot();
10833 //----------------------------------------------------------------------------------------------------------------------
10834 // vogl_gl_replayer::write_trim_file_internal
10835 //----------------------------------------------------------------------------------------------------------------------
10836 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)
10838 // Open the output trace
10839 // 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.
10840 const vogl_ctypes &trace_gl_ctypes = get_trace_gl_ctypes();
10842 vogl_trace_packet trace_packet(&trace_gl_ctypes);
10844 // TODO: This seems like WAY too much work! Move the snapshot to the beginning of the trace, in the header!
10845 bool found_state_snapshot = false;
10846 dynamic_string binary_snapshot_id, text_snapshot_id;
10848 bool is_at_start_of_trace = false;
10849 VOGL_NOTE_UNUSED(is_at_start_of_trace);
10851 int demarcation_packet_index = -1;
10852 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
10854 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
10855 if (packet_type != cTSPTGLEntrypoint)
10858 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
10860 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
10861 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
10864 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
10866 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
10870 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
10871 if (cmd == cITCRDemarcation)
10873 is_at_start_of_trace = true;
10874 demarcation_packet_index = packet_index;
10876 else if (cmd == cITCRKeyValueMap)
10878 key_value_map &kvm = trace_packet.get_key_value_map();
10880 dynamic_string cmd_type(kvm.get_string("command_type"));
10882 if (cmd_type == "state_snapshot")
10884 found_state_snapshot = true;
10886 text_snapshot_id = kvm.get_string("id");
10887 binary_snapshot_id = kvm.get_string("binary_id");
10892 vogl_trace_file_writer trace_writer(&trace_gl_ctypes);
10893 if (!trace_writer.open(trim_filename.get_ptr(), NULL, true, false, m_trace_pointer_size_in_bytes))
10895 console::error("%s: Failed creating trimmed trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
10899 if (found_state_snapshot)
10901 // Copy over the source trace's archive (it contains the snapshot, along with any files it refers to).
10902 if (trace_reader.get_archive_blob_manager().is_initialized())
10904 dynamic_string_array blob_files(trace_reader.get_archive_blob_manager().enumerate());
10905 for (uint i = 0; i < blob_files.size(); i++)
10907 if ((blob_files[i].is_empty()) || (blob_files[i] == VOGL_TRACE_ARCHIVE_FRAME_FILE_OFFSETS_FILENAME))
10910 vogl_message_printf("Adding blob file %s to output trace archive\n", blob_files[i].get_ptr());
10912 if (!trace_writer.get_trace_archive()->copy_file(trace_reader.get_archive_blob_manager(), blob_files[i], blob_files[i]).has_content())
10914 vogl_error_printf("%s: Failed copying blob data for file \"%s\" to output trace archive!\n", VOGL_FUNCTION_NAME, blob_files[i].get_ptr());
10922 // Copy over the source trace's backtrace map, machine info, etc. files.
10923 if (trace_reader.get_archive_blob_manager().is_initialized())
10925 // compiler_info.json
10926 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);
10927 // machine_info.json
10928 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);
10929 // backtrace_map_syms.json
10930 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);
10931 // backtrace_map_addrs.json
10932 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);
10935 vogl_unique_ptr<vogl_gl_state_snapshot> pTrim_snapshot(snapshot_state(&trim_packets, optimize_snapshot));
10937 if (!pTrim_snapshot.get())
10939 console::error("%s: Failed creating replayer GL snapshot!\n", VOGL_FUNCTION_NAME);
10943 pTrim_snapshot->set_frame_index(0);
10946 if (!pTrim_snapshot->serialize(*doc.get_root(), *trace_writer.get_trace_archive(), &trace_gl_ctypes))
10948 console::error("%s: Failed serializing GL state snapshot!\n", VOGL_FUNCTION_NAME);
10949 trace_writer.close();
10950 file_utils::delete_file(trim_filename.get_ptr());
10954 vogl::vector<char> snapshot_data;
10955 doc.serialize(snapshot_data, true, 0, false);
10957 uint8_vec binary_snapshot_data;
10958 doc.binary_serialize(binary_snapshot_data);
10960 pTrim_snapshot.reset();
10962 // Write the state_snapshot file to the trace archive
10963 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));
10964 if (snapshot_id.is_empty())
10966 console::error("%s: Failed adding GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
10967 trace_writer.close();
10968 file_utils::delete_file(trim_filename.get_ptr());
10973 *pSnapshot_id = snapshot_id;
10975 snapshot_data.clear();
10977 // Write the binary_state_snapshot file to the trace archive
10978 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));
10979 if (binary_snapshot_id.is_empty())
10981 console::error("%s: Failed adding binary GL snapshot file to output blob manager!\n", VOGL_FUNCTION_NAME);
10982 trace_writer.close();
10983 file_utils::delete_file(trim_filename.get_ptr());
10987 binary_snapshot_data.clear();
10989 key_value_map snapshot_key_value_map;
10990 snapshot_key_value_map.insert("command_type", "state_snapshot");
10991 snapshot_key_value_map.insert("id", snapshot_id);
10992 snapshot_key_value_map.insert("binary_id", binary_snapshot_id);
10994 dynamic_stream snapshot_stream(0);
10995 if (!vogl_write_glInternalTraceCommandRAD(snapshot_stream, &trace_gl_ctypes, cITCRKeyValueMap, sizeof(snapshot_key_value_map), reinterpret_cast<const GLubyte *>(&snapshot_key_value_map)))
10997 console::error("%s: Failed serializing snapshot packet!\n", VOGL_FUNCTION_NAME);
10998 trace_writer.close();
10999 file_utils::delete_file(trim_filename.get_ptr());
11003 if (demarcation_packet_index >= 0)
11005 trim_packets.insert(demarcation_packet_index, snapshot_stream.get_buf());
11006 demarcation_packet_index++;
11010 dynamic_stream demarcation_stream(0);
11011 vogl_write_glInternalTraceCommandRAD(demarcation_stream, &trace_gl_ctypes, cITCRDemarcation, 0, NULL);
11013 // Screw the ctypes packet, it's only used for debugging right now anyway.
11014 trim_packets.insert(0, snapshot_stream.get_buf());
11015 trim_packets.insert(1, demarcation_stream.get_buf());
11019 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11021 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11023 const bool is_swap = trim_packets.is_swap_buffers_packet(packet_index);
11025 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11026 if (packet_type == cTSPTEOF)
11028 else if (packet_type != cTSPTGLEntrypoint)
11030 VOGL_ASSERT_ALWAYS;
11033 if (!trace_writer.write_packet(packet_buf.get_ptr(), packet_buf.size(), is_swap))
11035 console::error("%s: Failed writing trace packet to output trace file \"%s\"!\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11036 trace_writer.close();
11037 file_utils::delete_file(trim_filename.get_ptr());
11042 bool success = trace_writer.close();
11044 console::error("%s: Failed closing wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11046 console::message("%s: Successfully wrote trim trace file \"%s\"\n", VOGL_FUNCTION_NAME, trim_filename.get_ptr());
11051 //----------------------------------------------------------------------------------------------------------------------
11052 // vogl_gl_replayer::write_trim_file
11053 //----------------------------------------------------------------------------------------------------------------------
11054 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)
11060 console::error("%s: Trace is not open\n", VOGL_METHOD_NAME);
11064 bool from_start_of_frame = (flags & cWriteTrimFileFromStartOfFrame) != 0;
11066 if ((!from_start_of_frame) || (!trim_len))
11067 flags &= ~cWriteTrimFileOptimizeSnapshot;
11069 const uint trim_frame = static_cast<uint>(get_frame_index());
11070 const int64_t trim_call_counter = get_last_parsed_call_counter();
11072 // Read the desired packets from the source trace file
11073 vogl_trace_packet_array trim_packets;
11075 if ((trim_len) || (!trim_frame))
11077 console::message("%s: Reading trim packets from source trace file\n", VOGL_FUNCTION_NAME);
11079 uint frames_to_read = trim_len;
11080 if ((from_start_of_frame) && (!trim_frame) && (!trim_len))
11081 frames_to_read = 1;
11083 uint actual_trim_len = 0;
11084 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);
11085 if (read_packets_status == vogl_trace_file_reader::cFailed)
11087 console::error("%s: Failed reading source trace file packets beginning at frame %u!\n", VOGL_FUNCTION_NAME, trim_frame);
11091 if (actual_trim_len != frames_to_read)
11093 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);
11096 if (from_start_of_frame)
11098 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);
11100 if ((!trim_frame) && (!trim_len))
11102 // 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.
11103 // TODO: Most of this will go away once we move the state snapshot into the trace archive.
11105 vogl_trace_packet_array new_trim_packets;
11107 vogl_trace_packet trace_packet(&get_trace_gl_ctypes());
11109 for (uint packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11111 const vogl_trace_stream_packet_types_t packet_type = trim_packets.get_packet_type(packet_index);
11112 if (packet_type != cTSPTGLEntrypoint)
11115 const uint8_vec &packet_buf = trim_packets.get_packet_buf(packet_index);
11117 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(packet_index);
11118 if (pGL_packet->m_entrypoint_id != VOGL_ENTRYPOINT_glInternalTraceCommandRAD)
11121 if (!trace_packet.deserialize(packet_buf.get_ptr(), packet_buf.size(), true))
11123 console::error("%s: Failed parsing glInternalTraceCommandRAD packet\n", VOGL_FUNCTION_NAME);
11127 GLuint cmd = trace_packet.get_param_value<GLuint>(0);
11129 new_trim_packets.push_back(packet_buf);
11131 if (cmd == cITCRDemarcation)
11135 trim_packets.swap(new_trim_packets);
11138 else if (trim_call_counter >= 0)
11140 uint orig_num_packets = trim_packets.size();
11141 uint total_erased_packets = 0;
11143 // Remove any calls before the current one.
11144 for (int64_t packet_index = 0; packet_index < trim_packets.size(); packet_index++)
11146 if (trim_packets.get_packet_type(static_cast<uint>(packet_index)) != cTSPTGLEntrypoint)
11149 const vogl_trace_gl_entrypoint_packet *pGL_packet = &trim_packets.get_packet<vogl_trace_gl_entrypoint_packet>(static_cast<uint>(packet_index));
11151 if (static_cast<int64_t>(pGL_packet->m_call_counter) <= trim_call_counter)
11153 trim_packets.erase(static_cast<uint>(packet_index));
11156 total_erased_packets++;
11160 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());
11164 return write_trim_file_internal(trim_packets, trim_filename, trace_reader, (flags & cWriteTrimFileOptimizeSnapshot) != 0, pSnapshot_id);