diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index 52e2b9c4b..7f34b1957 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -51,6 +51,37 @@ bool GL4Shader::Prepare() { return success; } +bool GL4Shader::LoadFromBinary(const uint8_t* blob, GLenum binary_format, + size_t length) { + program_ = glCreateProgram(); + glProgramBinary(program_, binary_format, blob, GLsizei(length)); + + GLint link_status = 0; + glGetProgramiv(program_, GL_LINK_STATUS, &link_status); + if (!link_status) { + // Failed to link. Not fatal - just clean up so we can get generated later. + XELOGD("GL4Shader::LoadFromBinary failed. Log:\n%s", + GetProgramInfoLog().c_str()); + glDeleteProgram(program_); + program_ = 0; + + return false; + } + + // Build static vertex array descriptor. + if (!PrepareVertexArrayObject()) { + XELOGE("Unable to prepare vertex shader array object"); + return false; + } + + // Success! + host_binary_ = GetBinary(); + host_disassembly_ = GetHostDisasmNV(host_binary_); + + is_valid_ = true; + return true; +} + bool GL4Shader::PrepareVertexArrayObject() { glCreateVertexArrays(1, &vao_); @@ -211,7 +242,7 @@ std::string GL4Shader::GetProgramInfoLog() { return log; } -std::vector GL4Shader::GetBinary() { +std::vector GL4Shader::GetBinary(GLenum* binary_format) { std::vector binary; // Get program binary, if it's available. @@ -219,9 +250,13 @@ std::vector GL4Shader::GetBinary() { glGetProgramiv(program_, GL_PROGRAM_BINARY_LENGTH, &binary_length); if (binary_length) { binary.resize(binary_length); - GLenum binary_format; - glGetProgramBinary(program_, binary_length, &binary_length, &binary_format, - binary.data()); + GLenum binary_format_tmp = 0; + glGetProgramBinary(program_, binary_length, &binary_length, + &binary_format_tmp, binary.data()); + + if (binary_format) { + *binary_format = binary_format_tmp; + } } return binary; diff --git a/src/xenia/gpu/gl4/gl4_shader.h b/src/xenia/gpu/gl4/gl4_shader.h index 91b1e6098..1f884ebf2 100644 --- a/src/xenia/gpu/gl4/gl4_shader.h +++ b/src/xenia/gpu/gl4/gl4_shader.h @@ -29,7 +29,9 @@ class GL4Shader : public Shader { GLuint shader() const { return shader_; } GLuint vao() const { return vao_; } - bool Prepare() override; + bool Prepare(); + bool LoadFromBinary(const uint8_t* blob, GLenum binary_format, size_t length); + std::vector GetBinary(GLenum* binary_format = nullptr); protected: bool PrepareVertexArrayObject(); @@ -38,7 +40,6 @@ class GL4Shader : public Shader { std::string GetShaderInfoLog(); std::string GetProgramInfoLog(); - std::vector GetBinary(); static std::string GetHostDisasmNV(const std::vector& binary); GLuint program_ = 0;