Skip to content

Commit

Permalink
game: Improve OpenGL version detection and make requirement errors mo…
Browse files Browse the repository at this point in the history
…re obvious to the user (#2787)
  • Loading branch information
xTVaser authored Jul 1, 2023
1 parent 5f8c21b commit 436bac8
Show file tree
Hide file tree
Showing 17 changed files with 6,837 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ include_directories(third-party/tree-sitter/tree-sitter/lib/include)
include_directories(third-party/tree-sitter/tree-sitter-opengoal/include)
add_subdirectory(third-party/tree-sitter EXCLUDE_FROM_ALL)

# native OS dialogs for error messages
add_subdirectory(third-party/libtinyfiledialogs)

string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

# build common library
Expand Down
3 changes: 2 additions & 1 deletion common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ add_library(common
util/dgo_util.cpp
util/DgoReader.cpp
util/DgoWriter.cpp
util/dialogs.cpp
util/diff.cpp
util/FileUtil.cpp
util/FontUtils.cpp
Expand All @@ -85,7 +86,7 @@ add_library(common
util/unicode_util.cpp
versions/versions.cpp)

target_link_libraries(common fmt lzokay replxx libzstd_static tree-sitter sqlite3)
target_link_libraries(common fmt lzokay replxx libzstd_static tree-sitter sqlite3 libtinyfiledialogs)

if(WIN32)
target_link_libraries(common wsock32 ws2_32 windowsapp)
Expand Down
10 changes: 10 additions & 0 deletions common/util/dialogs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "dialogs.h"

namespace dialogs {
// char const * const aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
// char const * const aIconType , /* "info" "warning" "error" "question" */
// int const aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
void create_error_message_dialog(const std::string& title, const std::string& message) {
tinyfd_messageBox(title.data(), message.data(), "ok", "error", 1);
}
} // namespace dialogs
9 changes: 9 additions & 0 deletions common/util/dialogs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <string>

#include "third-party/libtinyfiledialogs/tinyfiledialogs.h"

namespace dialogs {
void create_error_message_dialog(const std::string& title, const std::string& message);
}
1 change: 1 addition & 0 deletions game/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ set(RUNTIME_SOURCE
external/discord_jak2.cpp
graphics/display.cpp
graphics/gfx.cpp
graphics/gfx_test.cpp
graphics/jak2_texture_remap.cpp
graphics/opengl_renderer/background/background_common.cpp
graphics/opengl_renderer/background/Shrub.cpp
Expand Down
50 changes: 50 additions & 0 deletions game/graphics/gfx_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "gfx_test.h"

#include "game/system/hid/sdl_util.h"

namespace tests {
void to_json(json& j, const GPUTestOutput& obj) {
j = json{
{"success", obj.success},
{"error", obj.error},
{"errorCause", obj.errorCause},
};
}

GPUTestOutput run_gpu_test(const std::string& test_type) {
lg::info("Running GPU Test - {}", test_type);
GPUTestOutput output = {false, "", ""};
if (test_type == "opengl") {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
output = {false, "SDL initialization failed",
sdl_util::log_and_return_error("SDL initialization failed")};
return output;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_Window* window =
SDL_CreateWindow("OpenGL Version", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800,
600, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
if (!window) {
output = {false, "SDL window creation failed",
sdl_util::log_and_return_error("SDL initialization failed")};
SDL_Quit();
return output;
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext) {
output = {false, "Required OpenGL Version is not supported",
sdl_util::log_and_return_error("SDL initialization failed")};
} else {
output = {true, "", ""};
SDL_GL_DeleteContext(glContext);
}
SDL_DestroyWindow(window);
SDL_Quit();
} else {
lg::error("Invalid GPU test type - {}", test_type);
}
return output;
}
}; // namespace tests
16 changes: 16 additions & 0 deletions game/graphics/gfx_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <string>

#include "common/util/json_util.h"

namespace tests {
struct GPUTestOutput {
bool success;
std::string error;
std::string errorCause;
};
void to_json(json& j, const GPUTestOutput& obj);

GPUTestOutput run_gpu_test(const std::string& test_type);
} // namespace tests
19 changes: 19 additions & 0 deletions game/graphics/pipelines/opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "third-party/imgui/imgui_impl_sdl.h"
#include "third-party/imgui/imgui_style.h"
#define STBI_WINDOWS_UTF8
#include "common/util/dialogs.h"
#include "common/util/string_util.h"

#include "third-party/stb_image/stb_image.h"
Expand Down Expand Up @@ -99,6 +100,8 @@ static int gl_init(GfxGlobalSettings& settings) {
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0) {
sdl_util::log_error("Could not initialize SDL, exiting");
dialogs::create_error_message_dialog("Critical Error Encountered",
"Could not initialize SDL, exiting");
return 1;
}
}
Expand Down Expand Up @@ -216,6 +219,10 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
prof().end_event();
if (!window) {
sdl_util::log_error("gl_make_display failed - Could not create display window");
dialogs::create_error_message_dialog(
"Critical Error Encountered",
"Unable to create OpenGL window.\nOpenGOAL requires OpenGL 4.3.\nEnsure your GPU "
"supports this and your drivers are up to date.");
return NULL;
}

Expand All @@ -225,13 +232,21 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
prof().end_event();
if (!gl_context) {
sdl_util::log_error("gl_make_display failed - Could not create OpenGL Context");
dialogs::create_error_message_dialog(
"Critical Error Encountered",
"Unable to create OpenGL context.\nOpenGOAL requires OpenGL 4.3.\nEnsure your GPU "
"supports this and your drivers are up to date.");
return NULL;
}

{
auto p = scoped_prof("startup::sdl::assign_context");
if (SDL_GL_MakeCurrent(window, gl_context) != 0) {
sdl_util::log_error("gl_make_display failed - Could not associated context with window");
dialogs::create_error_message_dialog("Critical Error Encountered",
"Unable to create OpenGL window with context.\nOpenGOAL "
"requires OpenGL 4.3.\nEnsure your GPU "
"supports this and your drivers are up to date.");
return NULL;
}
}
Expand All @@ -242,6 +257,10 @@ static std::shared_ptr<GfxDisplay> gl_make_display(int width,
gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress);
if (!gladLoadGL()) {
lg::error("GL init fail");
dialogs::create_error_message_dialog("Critical Error Encountered",
"Unable to initialize OpenGL API.\nOpenGOAL requires "
"OpenGL 4.3.\nEnsure your GPU "
"supports this and your drivers are up to date.");
return NULL;
}
}
Expand Down
21 changes: 21 additions & 0 deletions game/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
#include "common/global_profiler/GlobalProfiler.h"
#include "common/log/log.h"
#include "common/util/FileUtil.h"
#include "common/util/dialogs.h"
#include "common/util/os.h"
#include "common/util/unicode_util.h"
#include "common/versions/versions.h"

#include "game/common/game_common_types.h"
#include "graphics/gfx_test.h"

#include "third-party/CLI11.hpp"

Expand Down Expand Up @@ -90,6 +92,8 @@ int main(int argc, char** argv) {
bool disable_display = false;
bool enable_debug_vm = false;
bool enable_profiling = false;
std::string gpu_test = "";
std::string gpu_test_out_path = "";
int port_number = -1;
fs::path project_path_override;
std::vector<std::string> game_args;
Expand All @@ -104,6 +108,10 @@ int main(int argc, char** argv) {
app.add_flag("--no-display", disable_display, "Disable video display");
app.add_flag("--vm", enable_debug_vm, "Enable debug PS2 VM (defaulted to off)");
app.add_flag("--profile", enable_profiling, "Enables profiling immediately from startup");
app.add_option("--gpu-test", gpu_test,
"Tests for minimum graphics requirements. Valid Options are: [opengl]");
app.add_option("--gpu-test-out-path", gpu_test_out_path,
"Where to store the gpu test result file");
app.add_option("--proj-path", project_path_override,
"Specify the location of the 'data/' folder");
app.footer(game_arg_documentation());
Expand All @@ -117,6 +125,17 @@ int main(int argc, char** argv) {
return 0;
}

if (!gpu_test.empty() && !gpu_test_out_path.empty()) {
const auto output = tests::run_gpu_test(gpu_test);
json data = output;
try {
file_util::write_text_file(gpu_test_out_path, data.dump(2));
} catch (std::exception& e) {
return 1;
}
return 0;
}

prof().set_enable(enable_profiling);

// Create struct with all non-kmachine handled args to pass to the runtime
Expand All @@ -132,6 +151,8 @@ int main(int argc, char** argv) {
// If the CPU doesn't have AVX, GOAL code won't work and we exit.
if (!get_cpu_info().has_avx) {
lg::info("Your CPU does not support AVX, which is required for OpenGOAL.");
dialogs::create_error_message_dialog(
"Unmet Requirements", "Your CPU does not support AVX, which is required for OpenGOAL.");
return -1;
}

Expand Down
5 changes: 5 additions & 0 deletions game/system/hid/sdl_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ void log_error(const std::string& msg) {
std::string sdl_cause = SDL_GetError();
lg::error("SDL Error: {} - Cause: {}", msg, sdl_cause.empty() ? "n/a" : sdl_cause);
}
std::string log_and_return_error(const std::string& msg) {
std::string sdl_cause = SDL_GetError();
lg::error("SDL Error: {} - Cause: {}", msg, sdl_cause.empty() ? "n/a" : sdl_cause);
return sdl_cause;
}
bool is_any_event_type(uint32_t event_type, const std::vector<uint32_t>& allowed_types) {
for (const auto& allowed_type : allowed_types) {
if (allowed_type == event_type) {
Expand Down
1 change: 1 addition & 0 deletions game/system/hid/sdl_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace sdl_util {
void log_error(const std::string& msg = "");
std::string log_and_return_error(const std::string& msg = "");
bool is_any_event_type(uint32_t event_type, const std::vector<uint32_t>& allowed_types);
SDL_bool sdl_bool(const bool val);
bool from_sdl_bool(const SDL_bool val);
Expand Down
4 changes: 4 additions & 0 deletions third-party/libtinyfiledialogs/CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 436bac8

Please sign in to comment.