From cf41a84fe3826558b7b827966e35ba6163a423d7 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 20 Dec 2015 20:53:31 -0600 Subject: [PATCH 01/10] Fix broken check against bool constants Fix always terminating execution in cexece branches (these are sometimes followed by exece branches) --- src/xenia/gpu/glsl_shader_translator.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/xenia/gpu/glsl_shader_translator.cc b/src/xenia/gpu/glsl_shader_translator.cc index 9311f5a1c..423ba191d 100644 --- a/src/xenia/gpu/glsl_shader_translator.cc +++ b/src/xenia/gpu/glsl_shader_translator.cc @@ -361,10 +361,10 @@ void GlslShaderTranslator::ProcessExecInstructionBegin( EmitSourceDepth("{\n"); break; case ParsedExecInstruction::Type::kConditional: - EmitSourceDepth("if ((state.bool_consts[%d] & (1 << %d)) == %c) {\n", + EmitSourceDepth("if ((state.bool_consts[%d] & (1 << %d)) %c= 0) {\n", instr.bool_constant_index / 32, instr.bool_constant_index % 32, - instr.condition ? '1' : '0'); + instr.condition ? '!' : '='); break; case ParsedExecInstruction::Type::kPredicated: EmitSourceDepth("if (%cp0) {\n", instr.condition ? ' ' : '!'); @@ -384,13 +384,13 @@ void GlslShaderTranslator::ProcessExecInstructionBegin( void GlslShaderTranslator::ProcessExecInstructionEnd( const ParsedExecInstruction& instr) { - Unindent(); - EmitSourceDepth("}\n"); if (instr.is_end) { EmitSourceDepth("pc = 0xFFFF;\n"); EmitSourceDepth("break;\n"); cf_wrote_pc_ = true; } + Unindent(); + EmitSourceDepth("}\n"); } void GlslShaderTranslator::ProcessLoopStartInstruction( @@ -494,10 +494,10 @@ void GlslShaderTranslator::ProcessJumpInstruction( EmitSourceDepth("{\n"); break; case ParsedJumpInstruction::Type::kConditional: - EmitSourceDepth("if ((state.bool_consts[%d] & (1 << %d)) == %c) {\n", + EmitSourceDepth("if ((state.bool_consts[%d] & (1 << %d)) %c= 0) {\n", instr.bool_constant_index / 32, instr.bool_constant_index % 32, - instr.condition ? '1' : '0'); + instr.condition ? '!' : '='); needs_fallthrough = true; break; case ParsedJumpInstruction::Type::kPredicated: From 0c60cc5f48987022071fff8e0957e676262768f1 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 20 Dec 2015 20:55:04 -0600 Subject: [PATCH 02/10] Fix GLContext::AssertExtensionsPresent not clearing the context after use --- src/xenia/ui/gl/gl_context.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xenia/ui/gl/gl_context.cc b/src/xenia/ui/gl/gl_context.cc index 7a6793bbf..97989999f 100644 --- a/src/xenia/ui/gl/gl_context.cc +++ b/src/xenia/ui/gl/gl_context.cc @@ -281,6 +281,8 @@ void GLContext::AssertExtensionsPresent() { "OpenGL extension ARB_fragment_coord_conventions is required."); return; } + + ClearCurrent(); } void GLContext::DebugMessage(GLenum source, GLenum type, GLuint id, From 30eda6909f5c03757466a9513b32d55d8e3ed2d2 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 20 Dec 2015 21:13:51 -0600 Subject: [PATCH 03/10] GLContext::WasLost - Determines if we lost the context due to a TDR or another outstanding event. --- src/xenia/ui/gl/gl_context.cc | 75 +++++++++++++++++++++++++-------- src/xenia/ui/gl/gl_context.h | 3 ++ src/xenia/ui/graphics_context.h | 6 +++ 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/xenia/ui/gl/gl_context.cc b/src/xenia/ui/gl/gl_context.cc index 97989999f..cc40e161d 100644 --- a/src/xenia/ui/gl/gl_context.cc +++ b/src/xenia/ui/gl/gl_context.cc @@ -133,20 +133,31 @@ bool GLContext::Initialize(GLContext* share_context) { return false; } + bool robust_access_supported = false; + if (GLEW_ARB_robustness) { + robust_access_supported = true; + } + int context_flags = 0; if (FLAGS_gl_debug) { context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; } + if (robust_access_supported) { + context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; + } - int attrib_list[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, - 4, - WGL_CONTEXT_MINOR_VERSION_ARB, - 5, - WGL_CONTEXT_FLAGS_ARB, - context_flags, - WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0}; + int attrib_list[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, + 4, + WGL_CONTEXT_MINOR_VERSION_ARB, + 5, + WGL_CONTEXT_FLAGS_ARB, + context_flags, + WGL_CONTEXT_PROFILE_MASK_ARB, + WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + robust_access_supported ? WGL_LOSE_CONTEXT_ON_RESET_ARB : 0, + 0}; glrc_ = wglCreateContextAttribsARB( dc_, share_context ? share_context->glrc_ : nullptr, attrib_list); @@ -196,20 +207,31 @@ std::unique_ptr GLContext::CreateOffscreen( { GraphicsContextLock context_lock(parent_context); + bool robust_access_supported = false; + if (GLEW_ARB_robustness) { + robust_access_supported = true; + } + int context_flags = 0; if (FLAGS_gl_debug) { context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; } + if (robust_access_supported) { + context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; + } - int attrib_list[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, - 4, - WGL_CONTEXT_MINOR_VERSION_ARB, - 5, - WGL_CONTEXT_FLAGS_ARB, - context_flags, - WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0}; + int attrib_list[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, + 4, + WGL_CONTEXT_MINOR_VERSION_ARB, + 5, + WGL_CONTEXT_FLAGS_ARB, + context_flags, + WGL_CONTEXT_PROFILE_MASK_ARB, + WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + robust_access_supported ? WGL_LOSE_CONTEXT_ON_RESET_ARB : 0, + 0}; new_glrc = wglCreateContextAttribsARB(parent_context->dc_, parent_context->glrc_, attrib_list); if (!new_glrc) { @@ -450,6 +472,23 @@ void GLContext::ClearCurrent() { } } +bool GLContext::WasLost() { + if (context_lost_) { + return true; + } + + auto status = glGetGraphicsResetStatusARB(); + if (status != GL_NO_ERROR) { + // Graphics card reset. + XELOGE("============= TDR detected on context %p! Context %s =============", + glrc_, status == GL_GUILTY_CONTEXT_RESET ? "guilty" : "innocent"); + context_lost_ = true; + return true; + } + + return false; +} + void GLContext::BeginSwap() { SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLContext::BeginSwap"); float clear_color[] = {238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.0f}; diff --git a/src/xenia/ui/gl/gl_context.h b/src/xenia/ui/gl/gl_context.h index 65d2beb5a..120ad4c03 100644 --- a/src/xenia/ui/gl/gl_context.h +++ b/src/xenia/ui/gl/gl_context.h @@ -40,6 +40,7 @@ class GLContext : public GraphicsContext { bool is_current() override; bool MakeCurrent() override; void ClearCurrent() override; + bool WasLost() override; void BeginSwap() override; void EndSwap() override; @@ -80,6 +81,8 @@ class GLContext : public GraphicsContext { Blitter blitter_; std::unique_ptr immediate_drawer_; + + bool context_lost_ = false; }; } // namespace gl diff --git a/src/xenia/ui/graphics_context.h b/src/xenia/ui/graphics_context.h index 1ca00dbc8..ef352099f 100644 --- a/src/xenia/ui/graphics_context.h +++ b/src/xenia/ui/graphics_context.h @@ -45,6 +45,12 @@ class GraphicsContext { virtual bool MakeCurrent() = 0; virtual void ClearCurrent() = 0; + // Returns true if the OS took away our context because we caused a TDR or + // some other outstanding error. When this happens, this context, as well as + // any other shared contexts are junk. + // This context must be made current in order for this call to work properly. + virtual bool WasLost() { return false; } + virtual void BeginSwap() = 0; virtual void EndSwap() = 0; From 59bee898f7569a2558659664d5a1ce27f763ef6b Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 14:41:18 -0600 Subject: [PATCH 04/10] Always output the shader info log if it's not empty. --- src/xenia/gpu/gl4/gl4_shader.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index 19a508345..2079772ef 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -135,18 +135,21 @@ bool GL4Shader::CompileProgram() { return false; } + // Output info log. + // log_length includes the null character. + GLint log_length = 0; + glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &log_length); + std::string info_log; + info_log.resize(log_length - 1); + glGetProgramInfoLog(program_, log_length, &log_length, &info_log[0]); + if (!info_log.empty()) { + XELOGD("Shader log: %s", info_log.c_str()); + } + // Get error log, if we failed to link. GLint link_status = 0; glGetProgramiv(program_, GL_LINK_STATUS, &link_status); if (!link_status) { - // log_length includes the null character. - GLint log_length = 0; - glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &log_length); - std::string info_log; - info_log.resize(log_length - 1); - glGetProgramInfoLog(program_, log_length, &log_length, - const_cast(info_log.data())); - XELOGE("Unable to link program: %s", info_log.c_str()); host_error_log_ = std::move(info_log); assert_always("Unable to link generated shader"); return false; From 919d3d080b10ff57983267fd8ee7bc2e190a027d Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 15:43:08 -0600 Subject: [PATCH 05/10] Assert on context loss due to a TDR --- src/xenia/gpu/gl4/gl4_command_processor.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/xenia/gpu/gl4/gl4_command_processor.cc b/src/xenia/gpu/gl4/gl4_command_processor.cc index 9855b137f..10666b53f 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.cc +++ b/src/xenia/gpu/gl4/gl4_command_processor.cc @@ -465,6 +465,12 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, // TODO(benvanik): prevent this? fences? glFinish(); + if (context_->WasLost()) { + // We've lost the context due to a TDR. + // TODO: Dump the current commands to a tracefile. + assert_always(); + } + // Remove any dead textures, etc. texture_cache_.Scavenge(); } @@ -581,8 +587,15 @@ bool GL4CommandProcessor::IssueDraw(PrimitiveType prim_type, if (!draw_batcher_.CommitDraw()) { return false; } + // TODO(benvanik): find a way to get around glVertexArrayVertexBuffer below. draw_batcher_.Flush(DrawBatcher::FlushMode::kMakeCoherent); + if (context_->WasLost()) { + // This draw lost us the context. This typically isn't hit. + assert_always(); + return false; + } + return true; } From ab93a6bf64aa25cecbd9063f77ea91023d936e14 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 15:44:02 -0600 Subject: [PATCH 06/10] If last framebuffer texture isn't set, use active framebuffer otherwise don't draw. --- src/xenia/gpu/gl4/gl4_command_processor.cc | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/xenia/gpu/gl4/gl4_command_processor.cc b/src/xenia/gpu/gl4/gl4_command_processor.cc index 10666b53f..de191e371 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.cc +++ b/src/xenia/gpu/gl4/gl4_command_processor.cc @@ -396,19 +396,24 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // HACK: just use whatever our current framebuffer is. GLuint framebuffer_texture = last_framebuffer_texture_; - /*GLuint framebuffer_texture = active_framebuffer_ - ? active_framebuffer_->color_targets[0] - : last_framebuffer_texture_;*/ + + if (last_framebuffer_texture_ == 0) { + framebuffer_texture = + active_framebuffer_ ? active_framebuffer_->color_targets[0] : 0; + } // Copy the the given framebuffer to the current backbuffer. Rect2D src_rect(0, 0, frontbuffer_width ? frontbuffer_width : 1280, frontbuffer_height ? frontbuffer_height : 720); Rect2D dest_rect(0, 0, swap_state_.width, swap_state_.height); - reinterpret_cast(context_.get()) - ->blitter() - ->CopyColorTexture2D(framebuffer_texture, src_rect, - static_cast(swap_state_.back_buffer_texture), - dest_rect, GL_LINEAR, true); + if (framebuffer_texture != 0) { + reinterpret_cast(context_.get()) + ->blitter() + ->CopyColorTexture2D( + framebuffer_texture, src_rect, + static_cast(swap_state_.back_buffer_texture), dest_rect, + GL_LINEAR, true); + } if (FLAGS_draw_all_framebuffers) { int32_t offsetx = (1280 - (1280 / 5)); From a4f6e60e20371a296f34a4f8b5e0486241349280 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 15:44:51 -0600 Subject: [PATCH 07/10] Blitter::Draw assert on zero src texture --- src/xenia/ui/gl/blitter.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xenia/ui/gl/blitter.cc b/src/xenia/ui/gl/blitter.cc index 21c2aec36..7501758ca 100644 --- a/src/xenia/ui/gl/blitter.cc +++ b/src/xenia/ui/gl/blitter.cc @@ -202,6 +202,8 @@ struct SavedState { void Blitter::Draw(GLuint src_texture, Rect2D src_rect, Rect2D dest_rect, GLenum filter) { + assert_not_zero(src_texture); + glDisable(GL_SCISSOR_TEST); glDisable(GL_STENCIL_TEST); glDisablei(GL_BLEND, 0); From cde39953ab0dcdf5ff7d1bd2b40cd47feca16e0d Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 15:46:39 -0600 Subject: [PATCH 08/10] Fix TracePlayer::PlayTraceOnThread not signifying it's done with the trace if a break is pending. --- src/xenia/gpu/trace_player.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index aea69e119..785db006d 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -156,6 +156,7 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, pending_packet = nullptr; } if (pending_break) { + playing_trace_ = false; return; } break; From b49114bad6ac9348110352187e678d7b07420cbc Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 15:53:51 -0600 Subject: [PATCH 09/10] GLContext: Keep track of robust access support for WasLost --- src/xenia/ui/gl/gl_context.cc | 21 ++++++++++++--------- src/xenia/ui/gl/gl_context.h | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/xenia/ui/gl/gl_context.cc b/src/xenia/ui/gl/gl_context.cc index cc40e161d..7a3da67c1 100644 --- a/src/xenia/ui/gl/gl_context.cc +++ b/src/xenia/ui/gl/gl_context.cc @@ -133,16 +133,15 @@ bool GLContext::Initialize(GLContext* share_context) { return false; } - bool robust_access_supported = false; if (GLEW_ARB_robustness) { - robust_access_supported = true; + robust_access_supported_ = true; } int context_flags = 0; if (FLAGS_gl_debug) { context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; } - if (robust_access_supported) { + if (robust_access_supported_) { context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; } @@ -156,7 +155,7 @@ bool GLContext::Initialize(GLContext* share_context) { WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - robust_access_supported ? WGL_LOSE_CONTEXT_ON_RESET_ARB : 0, + robust_access_supported_ ? WGL_LOSE_CONTEXT_ON_RESET_ARB : 0, 0}; glrc_ = wglCreateContextAttribsARB( @@ -207,15 +206,12 @@ std::unique_ptr GLContext::CreateOffscreen( { GraphicsContextLock context_lock(parent_context); - bool robust_access_supported = false; - if (GLEW_ARB_robustness) { - robust_access_supported = true; - } - int context_flags = 0; if (FLAGS_gl_debug) { context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; } + + bool robust_access_supported = parent_context->robust_access_supported_; if (robust_access_supported) { context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; } @@ -245,6 +241,8 @@ std::unique_ptr GLContext::CreateOffscreen( new_context->glrc_ = new_glrc; new_context->dc_ = GetDC(HWND(parent_context->target_window_->native_handle())); + new_context->robust_access_supported_ = + parent_context->robust_access_supported_; if (!new_context->MakeCurrent()) { FatalGLError("Could not make new GL context current."); return nullptr; @@ -473,6 +471,11 @@ void GLContext::ClearCurrent() { } bool GLContext::WasLost() { + if (!robust_access_supported_) { + // Can't determine if we lost the context. + return false; + } + if (context_lost_) { return true; } diff --git a/src/xenia/ui/gl/gl_context.h b/src/xenia/ui/gl/gl_context.h index 120ad4c03..a60e2d4ed 100644 --- a/src/xenia/ui/gl/gl_context.h +++ b/src/xenia/ui/gl/gl_context.h @@ -83,6 +83,7 @@ class GLContext : public GraphicsContext { std::unique_ptr immediate_drawer_; bool context_lost_ = false; + bool robust_access_supported_ = false; }; } // namespace gl From 990a8baf1b3523aed8f85f6ae78c5ba8e6deaa8c Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 22 Dec 2015 20:15:07 -0600 Subject: [PATCH 10/10] Fix cases where GL_INFO_LOG_LENGTH returns 0. --- src/xenia/gpu/gl4/gl4_shader.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index 2079772ef..d461cbfd2 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -140,8 +140,11 @@ bool GL4Shader::CompileProgram() { GLint log_length = 0; glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &log_length); std::string info_log; - info_log.resize(log_length - 1); - glGetProgramInfoLog(program_, log_length, &log_length, &info_log[0]); + if (log_length > 0) { + info_log.resize(log_length - 1); + glGetProgramInfoLog(program_, log_length, &log_length, &info_log[0]); + } + if (!info_log.empty()) { XELOGD("Shader log: %s", info_log.c_str()); }