Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crashing on startup with AMD GPUs #949

Merged
merged 2 commits into from
Mar 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 104 additions & 104 deletions Engine/OSGLContext_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,6 @@ static std::string GetGPUInfoAMDInternal_string(const OSGLContext_wgl_data* wglI

static bool GetGPUInfoAMDInternal_int(const OSGLContext_wgl_data* wglInfo, UINT gpuID, int info, int* value)
{

std::vector<unsigned int> data;
int totalSize = 0;

Expand All @@ -719,6 +718,36 @@ static bool GetGPUInfoAMDInternal_int(const OSGLContext_wgl_data* wglInfo, UINT
return true;
}

namespace {
class ScopedGLContext {
public:
ScopedGLContext(const GLRendererID& gid) {
assert(!OSGLContext_win::threadHasACurrentContext());
try {
_context = std::make_unique<OSGLContext_win>(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, gid, nullptr);
} catch (const std::exception& e) {
std::cerr << "Failed to create GL context : " << e.what() << std::endl;
return;
}

if (!OSGLContext_win::makeContextCurrent(_context.get())) {
_context.reset();
}
}

~ScopedGLContext() {
if (_context) {
OSGLContext_win::makeContextCurrent(nullptr);
}
}

explicit operator bool() const { return (bool)_context; }

private:
std::unique_ptr<OSGLContext_win> _context;
};
} // namespace

void
OSGLContext_win::getGPUInfos(std::list<OpenGLRendererInfo>& renderers)
{
Expand Down Expand Up @@ -749,37 +778,27 @@ OSGLContext_win::getGPUInfos(std::list<OpenGLRendererInfo>& renderers)
for (std::size_t i = 0; i < gpuHandles.size(); ++i) {
OpenGLRendererInfo info;
info.rendererID.rendererHandle = (void*)gpuHandles[i];
{
ScopedGLContext scopedContext(info.rendererID);
if (!scopedContext) {
continue;
}

std::unique_ptr<OSGLContext_win> context;
try {
GLRendererID gid;
gid.rendererHandle = info.rendererID.rendererHandle;
context.reset( new OSGLContext_win(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, gid, 0) );
} catch (const std::exception& e) {
continue;
}

if ( !makeContextCurrent( context.get() ) ) {
continue;
}
try {
OSGLContext::checkOpenGLVersion();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
continue;
}

try {
OSGLContext::checkOpenGLVersion();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
makeContextCurrent(nullptr);
continue;
info.vendorName = std::string( (const char *) glGetString(GL_VENDOR) );
info.rendererName = std::string( (const char *) glGetString(GL_RENDERER) );
info.glVersionString = std::string( (const char *) glGetString(GL_VERSION) );
info.glslVersionString = std::string( (const char*)glGetString (GL_SHADING_LANGUAGE_VERSION) );
info.maxMemBytes = nvx_get_GPU_mem_info();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
renderers.push_back(info);
}

info.vendorName = std::string( (const char *) glGetString(GL_VENDOR) );
info.rendererName = std::string( (const char *) glGetString(GL_RENDERER) );
info.glVersionString = std::string( (const char *) glGetString(GL_VERSION) );
info.glslVersionString = std::string( (const char*)glGetString (GL_SHADING_LANGUAGE_VERSION) );
info.maxMemBytes = nvx_get_GPU_mem_info();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
renderers.push_back(info);

makeContextCurrent(nullptr);
}
} else if (wglInfo->AMD_gpu_association && !isApplication32Bits()) {
//https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
Expand All @@ -798,62 +817,52 @@ OSGLContext_win::getGPUInfos(std::list<OpenGLRendererInfo>& renderers)
UINT gpuID = gpuIDs[index];

OpenGLRendererInfo info;
info.rendererName = GetGPUInfoAMDInternal_string(wglInfo, gpuID, WGL_GPU_RENDERER_STRING_AMD);
if (info.rendererName.empty()) {
continue;
}

info.vendorName = GetGPUInfoAMDInternal_string(wglInfo, gpuID, WGL_GPU_VENDOR_AMD);
if (info.vendorName.empty()) {
continue;
}
info.rendererID.renderID = gpuID;

info.glVersionString = GetGPUInfoAMDInternal_string(wglInfo, gpuID, WGL_GPU_OPENGL_VERSION_STRING_AMD);
if (info.glVersionString.empty()) {
continue;
}
{
ScopedGLContext scopedContext(info.rendererID);
if (!scopedContext) {
continue;
}

// note: cannot retrieve GL_SHADING_LANGUAGE_VERSION
info.rendererName = GetGPUInfoAMDInternal_string(wglInfo, gpuID, WGL_GPU_RENDERER_STRING_AMD);
if (info.rendererName.empty()) {
continue;
}

info.maxMemBytes = 0;
if (!isApplication32Bits()) {
int ramMB = 0;
// AMD drivers are f*** up in 32 bits, they read a wrong buffer size.
// It works fine in 64 bits mode
if (!GetGPUInfoAMDInternal_int(wglInfo, gpuID, WGL_GPU_RAM_AMD, &ramMB)) {
info.vendorName = GetGPUInfoAMDInternal_string(wglInfo, gpuID, WGL_GPU_VENDOR_AMD);
if (info.vendorName.empty()) {
continue;
}
info.maxMemBytes = ramMB * 1e6;
}

info.rendererID.renderID = gpuID;

std::unique_ptr<OSGLContext_win> context;
info.glVersionString = GetGPUInfoAMDInternal_string(wglInfo, gpuID, WGL_GPU_OPENGL_VERSION_STRING_AMD);
if (info.glVersionString.empty()) {
continue;
}

GLRendererID gid;
gid.renderID = info.rendererID.renderID;
try {
context.reset( new OSGLContext_win(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, gid, 0) );
} catch (const std::exception& e) {
continue;
}
// note: cannot retrieve GL_SHADING_LANGUAGE_VERSION

info.maxMemBytes = 0;
if (!isApplication32Bits()) {
int ramMB = 0;
// AMD drivers are f*** up in 32 bits, they read a wrong buffer size.
// It works fine in 64 bits mode
if (!GetGPUInfoAMDInternal_int(wglInfo, gpuID, WGL_GPU_RAM_AMD, &ramMB)) {
continue;
}
info.maxMemBytes = ramMB * 1e6;
}

if ( !makeContextCurrent( context.get() ) ) {
continue;
}
try {
OSGLContext::checkOpenGLVersion();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
continue;
}

try {
OSGLContext::checkOpenGLVersion();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
makeContextCurrent(nullptr);
continue;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
renderers.push_back(info);
}

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
renderers.push_back(info);

makeContextCurrent(nullptr);
}
}
}
Expand All @@ -863,38 +872,29 @@ OSGLContext_win::getGPUInfos(std::list<OpenGLRendererInfo>& renderers)
}
if (defaultFallback) {
// No extension, use default
std::unique_ptr<OSGLContext_win> context;
try {
context.reset( new OSGLContext_win(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, GLRendererID(), 0) );
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;

return;
}
{
ScopedGLContext scopedContext{GLRendererID()};
if (!scopedContext) {
return;
}

if ( !makeContextCurrent( context.get() ) ) {
return;
}
try {
OSGLContext::checkOpenGLVersion();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return;
}

try {
OSGLContext::checkOpenGLVersion();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
makeContextCurrent(nullptr);
return;
OpenGLRendererInfo info;
info.vendorName = std::string( (const char *) glGetString(GL_VENDOR) );
info.rendererName = std::string( (const char *) glGetString(GL_RENDERER) );
info.glVersionString = std::string( (const char *) glGetString(GL_VERSION) );
info.glslVersionString = std::string( (const char *) glGetString (GL_SHADING_LANGUAGE_VERSION) );
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
// We don't have any way to get memory size, set it to 0
info.maxMemBytes = nvx_get_GPU_mem_info();
renderers.push_back(info);
}

OpenGLRendererInfo info;
info.vendorName = std::string( (const char *) glGetString(GL_VENDOR) );
info.rendererName = std::string( (const char *) glGetString(GL_RENDERER) );
info.glVersionString = std::string( (const char *) glGetString(GL_VERSION) );
info.glslVersionString = std::string( (const char *) glGetString (GL_SHADING_LANGUAGE_VERSION) );
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
// We don't have any way to get memory size, set it to 0
info.maxMemBytes = nvx_get_GPU_mem_info();
renderers.push_back(info);

makeContextCurrent(nullptr);
}
} // OSGLContext_win::getGPUInfos

Expand Down