Merge pull request #492 from DrChat/gl_backend_changes

GL Backend Changes/Fixes
This commit is contained in:
Ben Vanik 2015-12-22 23:52:46 -08:00
commit 3b11de2c2d
8 changed files with 121 additions and 40 deletions

View File

@ -396,19 +396,24 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// HACK: just use whatever our current framebuffer is. // HACK: just use whatever our current framebuffer is.
GLuint framebuffer_texture = last_framebuffer_texture_; GLuint framebuffer_texture = last_framebuffer_texture_;
/*GLuint framebuffer_texture = active_framebuffer_
? active_framebuffer_->color_targets[0] if (last_framebuffer_texture_ == 0) {
: last_framebuffer_texture_;*/ framebuffer_texture =
active_framebuffer_ ? active_framebuffer_->color_targets[0] : 0;
}
// Copy the the given framebuffer to the current backbuffer. // Copy the the given framebuffer to the current backbuffer.
Rect2D src_rect(0, 0, frontbuffer_width ? frontbuffer_width : 1280, Rect2D src_rect(0, 0, frontbuffer_width ? frontbuffer_width : 1280,
frontbuffer_height ? frontbuffer_height : 720); frontbuffer_height ? frontbuffer_height : 720);
Rect2D dest_rect(0, 0, swap_state_.width, swap_state_.height); Rect2D dest_rect(0, 0, swap_state_.width, swap_state_.height);
reinterpret_cast<xe::ui::gl::GLContext*>(context_.get()) if (framebuffer_texture != 0) {
->blitter() reinterpret_cast<xe::ui::gl::GLContext*>(context_.get())
->CopyColorTexture2D(framebuffer_texture, src_rect, ->blitter()
static_cast<GLuint>(swap_state_.back_buffer_texture), ->CopyColorTexture2D(
dest_rect, GL_LINEAR, true); framebuffer_texture, src_rect,
static_cast<GLuint>(swap_state_.back_buffer_texture), dest_rect,
GL_LINEAR, true);
}
if (FLAGS_draw_all_framebuffers) { if (FLAGS_draw_all_framebuffers) {
int32_t offsetx = (1280 - (1280 / 5)); int32_t offsetx = (1280 - (1280 / 5));
@ -465,6 +470,12 @@ void GL4CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
// TODO(benvanik): prevent this? fences? // TODO(benvanik): prevent this? fences?
glFinish(); 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. // Remove any dead textures, etc.
texture_cache_.Scavenge(); texture_cache_.Scavenge();
} }
@ -581,8 +592,15 @@ bool GL4CommandProcessor::IssueDraw(PrimitiveType prim_type,
if (!draw_batcher_.CommitDraw()) { if (!draw_batcher_.CommitDraw()) {
return false; return false;
} }
// TODO(benvanik): find a way to get around glVertexArrayVertexBuffer below. // TODO(benvanik): find a way to get around glVertexArrayVertexBuffer below.
draw_batcher_.Flush(DrawBatcher::FlushMode::kMakeCoherent); 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; return true;
} }

View File

@ -135,18 +135,24 @@ bool GL4Shader::CompileProgram() {
return false; 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;
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());
}
// Get error log, if we failed to link. // Get error log, if we failed to link.
GLint link_status = 0; GLint link_status = 0;
glGetProgramiv(program_, GL_LINK_STATUS, &link_status); glGetProgramiv(program_, GL_LINK_STATUS, &link_status);
if (!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<char*>(info_log.data()));
XELOGE("Unable to link program: %s", info_log.c_str());
host_error_log_ = std::move(info_log); host_error_log_ = std::move(info_log);
assert_always("Unable to link generated shader"); assert_always("Unable to link generated shader");
return false; return false;

View File

@ -361,10 +361,10 @@ void GlslShaderTranslator::ProcessExecInstructionBegin(
EmitSourceDepth("{\n"); EmitSourceDepth("{\n");
break; break;
case ParsedExecInstruction::Type::kConditional: 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.bool_constant_index % 32, instr.bool_constant_index % 32,
instr.condition ? '1' : '0'); instr.condition ? '!' : '=');
break; break;
case ParsedExecInstruction::Type::kPredicated: case ParsedExecInstruction::Type::kPredicated:
EmitSourceDepth("if (%cp0) {\n", instr.condition ? ' ' : '!'); EmitSourceDepth("if (%cp0) {\n", instr.condition ? ' ' : '!');
@ -384,13 +384,13 @@ void GlslShaderTranslator::ProcessExecInstructionBegin(
void GlslShaderTranslator::ProcessExecInstructionEnd( void GlslShaderTranslator::ProcessExecInstructionEnd(
const ParsedExecInstruction& instr) { const ParsedExecInstruction& instr) {
Unindent();
EmitSourceDepth("}\n");
if (instr.is_end) { if (instr.is_end) {
EmitSourceDepth("pc = 0xFFFF;\n"); EmitSourceDepth("pc = 0xFFFF;\n");
EmitSourceDepth("break;\n"); EmitSourceDepth("break;\n");
cf_wrote_pc_ = true; cf_wrote_pc_ = true;
} }
Unindent();
EmitSourceDepth("}\n");
} }
void GlslShaderTranslator::ProcessLoopStartInstruction( void GlslShaderTranslator::ProcessLoopStartInstruction(
@ -494,10 +494,10 @@ void GlslShaderTranslator::ProcessJumpInstruction(
EmitSourceDepth("{\n"); EmitSourceDepth("{\n");
break; break;
case ParsedJumpInstruction::Type::kConditional: 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.bool_constant_index % 32, instr.bool_constant_index % 32,
instr.condition ? '1' : '0'); instr.condition ? '!' : '=');
needs_fallthrough = true; needs_fallthrough = true;
break; break;
case ParsedJumpInstruction::Type::kPredicated: case ParsedJumpInstruction::Type::kPredicated:

View File

@ -156,6 +156,7 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data,
pending_packet = nullptr; pending_packet = nullptr;
} }
if (pending_break) { if (pending_break) {
playing_trace_ = false;
return; return;
} }
break; break;

View File

@ -202,6 +202,8 @@ struct SavedState {
void Blitter::Draw(GLuint src_texture, Rect2D src_rect, Rect2D dest_rect, void Blitter::Draw(GLuint src_texture, Rect2D src_rect, Rect2D dest_rect,
GLenum filter) { GLenum filter) {
assert_not_zero(src_texture);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
glDisablei(GL_BLEND, 0); glDisablei(GL_BLEND, 0);

View File

@ -133,20 +133,30 @@ bool GLContext::Initialize(GLContext* share_context) {
return false; return false;
} }
if (GLEW_ARB_robustness) {
robust_access_supported_ = true;
}
int context_flags = 0; int context_flags = 0;
if (FLAGS_gl_debug) { if (FLAGS_gl_debug) {
context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; 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, int attrib_list[] = {
4, WGL_CONTEXT_MAJOR_VERSION_ARB,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
5, WGL_CONTEXT_MINOR_VERSION_ARB,
WGL_CONTEXT_FLAGS_ARB, 5,
context_flags, WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, context_flags,
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, WGL_CONTEXT_PROFILE_MASK_ARB,
0}; 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( glrc_ = wglCreateContextAttribsARB(
dc_, share_context ? share_context->glrc_ : nullptr, attrib_list); dc_, share_context ? share_context->glrc_ : nullptr, attrib_list);
@ -201,15 +211,23 @@ std::unique_ptr<GLContext> GLContext::CreateOffscreen(
context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
} }
int attrib_list[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, bool robust_access_supported = parent_context->robust_access_supported_;
4, if (robust_access_supported) {
WGL_CONTEXT_MINOR_VERSION_ARB, context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
5, }
WGL_CONTEXT_FLAGS_ARB,
context_flags, int attrib_list[] = {
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_MAJOR_VERSION_ARB,
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 4,
0}; 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_, new_glrc = wglCreateContextAttribsARB(parent_context->dc_,
parent_context->glrc_, attrib_list); parent_context->glrc_, attrib_list);
if (!new_glrc) { if (!new_glrc) {
@ -223,6 +241,8 @@ std::unique_ptr<GLContext> GLContext::CreateOffscreen(
new_context->glrc_ = new_glrc; new_context->glrc_ = new_glrc;
new_context->dc_ = new_context->dc_ =
GetDC(HWND(parent_context->target_window_->native_handle())); GetDC(HWND(parent_context->target_window_->native_handle()));
new_context->robust_access_supported_ =
parent_context->robust_access_supported_;
if (!new_context->MakeCurrent()) { if (!new_context->MakeCurrent()) {
FatalGLError("Could not make new GL context current."); FatalGLError("Could not make new GL context current.");
return nullptr; return nullptr;
@ -281,6 +301,8 @@ void GLContext::AssertExtensionsPresent() {
"OpenGL extension ARB_fragment_coord_conventions is required."); "OpenGL extension ARB_fragment_coord_conventions is required.");
return; return;
} }
ClearCurrent();
} }
void GLContext::DebugMessage(GLenum source, GLenum type, GLuint id, void GLContext::DebugMessage(GLenum source, GLenum type, GLuint id,
@ -448,6 +470,28 @@ 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;
}
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() { void GLContext::BeginSwap() {
SCOPE_profile_cpu_i("gpu", "xe::ui::gl::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}; float clear_color[] = {238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.0f};

View File

@ -40,6 +40,7 @@ class GLContext : public GraphicsContext {
bool is_current() override; bool is_current() override;
bool MakeCurrent() override; bool MakeCurrent() override;
void ClearCurrent() override; void ClearCurrent() override;
bool WasLost() override;
void BeginSwap() override; void BeginSwap() override;
void EndSwap() override; void EndSwap() override;
@ -80,6 +81,9 @@ class GLContext : public GraphicsContext {
Blitter blitter_; Blitter blitter_;
std::unique_ptr<GLImmediateDrawer> immediate_drawer_; std::unique_ptr<GLImmediateDrawer> immediate_drawer_;
bool context_lost_ = false;
bool robust_access_supported_ = false;
}; };
} // namespace gl } // namespace gl

View File

@ -45,6 +45,12 @@ class GraphicsContext {
virtual bool MakeCurrent() = 0; virtual bool MakeCurrent() = 0;
virtual void ClearCurrent() = 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 BeginSwap() = 0;
virtual void EndSwap() = 0; virtual void EndSwap() = 0;