Skip to content

Fix macos build and run issues #1777

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

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

Skosulor
Copy link

The goal of this pull request is to fix build and run issues for macOs.

  • Run presenter in the main thread (macos starts a hissy fit unless GUI related stuff is not run in the main thread)
  • Remove guards stopping QT events to be processed on macos
  • Fix shaders that for an unknown reason crashes when glLinkProgram is called.

Note: Requires some additional tweeks

@Skosulor
Copy link
Author

Changing the structure of engine.loop have resulted in some new issues that need to be fixed, error output:

INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/frigate/frigate.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/destroyer/heavy_destroyer.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/frigate/advanced_frigate.nyan
 ERR file:///Users/hell/repos/openage/assets/test/qml/main.qml:5 module "yay.sfttech.openage" is not installed

INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/destroyer/destroyer.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/cruiser/advanced_cruiser.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/anti_air_destroyer/heavy_anti_air_destroyer.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/anti_air_destroyer/anti_air_destroyer.nyan

FATAL: terminate has been called

uncaught exception

std::exception of type std::__1::system_error: mutex lock failed: Invalid argument

current stack:

Traceback (most recent call last):
  File ?, in _pthread_start+0x88 [0x1a005c2e4]
  File ?, in void* std::__1::__thread_proxy[abi:ne200100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>>(void*)+0x54 [0x103168358]
  File ?, in void std::__1::__thread_execute[abi:ne200100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>&, std::__1::__tuple_indices<...>)+0x1c [0x1031686a0]
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/anti_air_destroyer/projectiles/anti_air_destroyer_projectiles.nyan
  File ?, in decltype(std::declval<openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>()()) std::__1::__invoke[abi:ne200100]<openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>(openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0&&)+0x18 [0x103168704]
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/troop_center/troop_center.nyan
  File ?, in openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0::operator()() const+0x28 [0x103168760]
  File ?, in openage::time::TimeLoop::run()+0x40 [0x1035bb708]
  File ?, in openage::time::Clock::update_time()+0x218 [0x1035bad20]
  File ?, in std::__1::unique_lock<std::__1::shared_mutex>::~unique_lock[abi:ne200100]()+0x1c [0x1031c4e14]
  File ?, in std::__1::shared_mutex::unlock[abi:ne200100]() [0x1031d3b80]
  File ?, in std::terminate()+0x6c [0x1a00116b4]
  File ?, in std::__terminate(void (*)())+0x10 [0x1a0011710]
  File ?, in openage::error::terminate_handler()+0x278 [0x103170b90]

handing over to the system...

@Skosulor Skosulor force-pushed the fix_macos_build_and_run_issues branch from 2e546ba to e72b2e1 Compare May 18, 2025 12:34
@Skosulor
Copy link
Author

I set breakpoints around at destructors and got:

INFO [T2] Loading .nyan file: swgb_base/data/tech/generic/fusion_extractor/fusion_extractor.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/prefab_shelter/prefab_shelter.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/shipyard/shipyard.nyan
 ERR file:///Users/hell/repos/openage/assets/test/qml/main.qml:5 module "yay.sfttech.openage" is not installed

Process 42228 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
    frame #0: 0x00000001024e4864 libopenage.0.dylib`openage::engine::Engine::~Engine(this=0x000000016fdfd898) at engine.h:88:20
   85           Engine &operator=(const Engine &) = delete;
   86           Engine(Engine &&) = delete;
   87           Engine &operator=(Engine &&) = delete;
-> 88           ~Engine() = default;
   89  
   90  
   91           /**
Target 0: (run) stopped.

Not sure how to interpret this. What can I do to debug main.qml?

@heinezen
Copy link
Member

You can ignore the QML error. It has nothing to do with this. It only happens because our GUI is currently deactivated.

@Skosulor
Copy link
Author

Skosulor commented May 18, 2025

I'm a bit dumbfounded, when the deconstructor for Engine is called I have the following backtrace:

 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00000001024e4864 libopenage.0.dylib`openage::engine::Engine::~Engine(this=0x000000016fdfd898) at engine.h:88:20
   85           Engine &operator=(const Engine &) = delete;
   86           Engine(Engine &&) = delete;
   87           Engine &operator=(Engine &&) = delete;
-> 88           ~Engine() = default;
   89  
   90  
   91           /**
Target 0: (run) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x00000001024e4864 libopenage.0.dylib`openage::engine::Engine::~Engine(this=0x000000016fdfd898) at engine.h:88:20
    frame #1: 0x00000001024e457c libopenage.0.dylib`openage::run_game(args=0x000000016fdfddf8) at main.cpp:61:1

Which means that we have come to the end of run_game(). But I also have breakpoints inside the engine.loop function just after the presentation.run() is called.

void Engine::loop() {

	// if presenter is used, run the simulation in a separate thread
	if (this->run_mode == mode::FULL) {

		this->threads.emplace_back([&]() {
			this->loop_simulation();
		});

		this->presenter->run(this->window_settings);
		log::log(MSG(info) << "presenter exited");       
		// Make sure that the presenter gets destructed in the same thread
		// otherwise OpenGL complains about missing contexts
		this->presenter.reset();
		this->running = false;
	}
	else {
		this->loop_simulation();
	}
}

And the execution is never stopped inside the loop() function, nor is log::log(MSG(info) << "presenter exited"); executed.

So it seems that the presenter never exits.

Which lead me to debugging the presenter again, and it seems I ever get past init_graphics(), specifically the call to

	this->gui = std::make_shared<renderer::gui::GUI>(
		this->gui_app, // Qt application wrapper
		this->window,  // window for the gui
		qml_root_file, // entry qml file, absolute path.
		qml_root,      // directory to watch for qml file changes
		qml_assets,    // qml data: Engine *, the data directory, ...
		this->renderer // openage renderer
	);

Seem to halt the execution of the thread, at least I never get past it before the errors. I tried to remove main.qml to see what happens.

I would expect an error thrown from:

	this->gui = std::make_shared<renderer::gui::GUI>(
		this->gui_app, // Qt application wrapper
		this->window,  // window for the gui
		qml_root_file, // entry qml file, absolute path.
		qml_root,      // directory to watch for qml file changes
		qml_assets,    // qml data: Engine *, the data directory, ...
		this->renderer // openage renderer
	);

But instead I see an endless spam of errors, see the gist: https://gist.github.com/Skosulor/0ca46ceeb1c160d88ec0582cce25d1b2

It continues like that for like a couple hundred of thousand lines.

I found that it is actually in the log message when getting the path:

std::string Path::resolve_native_path_w() const {
	auto resolved_path = this->fsobj->resolve_w(this->parts);

	if (resolved_path.first) {
		return resolved_path.second.get_native_path();
	}
	else {
		throw Error{ERR << "failed to locate writable path: " << *this};
	}

I end up in the else clause. I find it a bit weird that I get so much output when an error is thrown.

Anyway, it seems to me that the error I receive: ERR file:///Users/hell/repos/openage/assets/test/qml/main.qml:5 module "yay.sfttech.openage" is not installed

Is related to the presenter failing to initialize graphics as qml_root_file is the main.qml file which imports yay.sfttech.openage

EDIT:

Nevermind yay.sfttech.openage is not the issue, I just removed the import and I got no error but the same result.

The main thread does not seem to get passed the:

	this->gui = std::make_shared<renderer::gui::GUI>(
		this->gui_app, // Qt application wrapper
		this->window,  // window for the gui
		qml_root_file, // entry qml file, absolute path.
		qml_root,      // directory to watch for qml file changes
		qml_assets,    // qml data: Engine *, the data directory, ...
		this->renderer // openage renderer
	);

Code inside presenter.cpp

@Skosulor
Copy link
Author

Okay I think I found it, it seems to be more shader problems.

Actually crashing on: auto maptex_shader = this->renderer->add_shader({id_shader_src, maptex_frag_shader_src});
In void GUI::initialize_render_pass

and digging deeper I found that the shader compilation fails:

CleanShot 2025-05-18 at 20 16 35@2x

As seen in the screenshot above GLShader::GLShader fails to compile the shader and for somereason macos does not like exceptions and I get the output seen in the gist earlier.

To conclude my debugging I guess there are two issues

  1. The shaders (identity and/or maptexture?)
  2. Handling of expection (on macos) which results in a spam of error messages of which none is the actual error

@heinezen
Copy link
Member

Can you comment the whole of GUI init and rendering out in the presenter? Maybe this fixes it. The GUI is not drawing anything anyway currently.

this->init_gui();

and

this->gui->render();

@heinezen
Copy link
Member

heinezen commented May 18, 2025

I think the issue is that the shader code is too old for the shaders in the GUI. They are based on OpenGL 1.2...

@Skosulor
Copy link
Author

I think the issue is that the shader code is too old for the shaders in the GUI. They are based on OpenGL 1.2...

Yup, I just found it! And you are correct, I updated them and that part works now.

However now I think there are a new issue..

INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/frigate/frigate.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/destroyer/heavy_destroyer.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/frigate/advanced_frigate.nyan
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/destroyer/destroyer.nyan
INFO Created OpenGL shader program

FATAL: terminate has been called

uncaught exception

std::exception of type std::__1::system_error: mutex lock failed: Invalid argument

current stack:

Traceback (most recent call last):
  File ?, in _pthread_start+0x88 [0x1a005c2e4]
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/cruiser/advanced_cruiser.nyan
  File ?, in void* std::__1::__thread_proxy[abi:ne200100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>>(void*)+0x54 [0x102ec8424]
  File ?, in void std::__1::__thread_execute[abi:ne200100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>&, std::__1::__tuple_indices<...>)+0x1c [0x102ec876c]
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/anti_air_destroyer/heavy_anti_air_destroyer.nyan
  File ?, in decltype(std::declval<openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>()()) std::__1::__invoke[abi:ne200100]<openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0>(openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0&&)+0x18 [0x102ec87d0]
  File ?, in openage::engine::Engine::Engine(openage::engine::Engine::mode, openage::util::Path const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&, openage::renderer::window_settings const&)::$_0::operator()() const+0x28 [0x102ec882c]
INFO [T2] Loading .nyan file: swgb_base/data/game_entity/generic/anti_air_destroyer/anti_air_destroyer.nyan
  File ?, in openage::time::TimeLoop::run()+0x40 [0x10331ff40]
  File ?, in openage::time::Clock::update_time()+0x218 [0x10331f558]
  File ?, in std::__1::unique_lock<std::__1::shared_mutex>::~unique_lock[abi:ne200100]()+0x1c [0x102f24ea8]
  File ?, in std::__1::shared_mutex::unlock[abi:ne200100]() [0x102f33c14]
  File ?, in std::terminate()+0x6c [0x1a00116b4]
  File ?, in std::__terminate(void (*)())+0x10 [0x1a0011710]
  File ?, in openage::error::terminate_handler()+0x278 [0x102ed0c24]

@heinezen
Copy link
Member

We should be almost there. The last renderer sytem that is initialized after the GUI is the final render pass that composes all other renderers. However, that has a very simple shader.

@heinezen heinezen added os: macos macOS-specific issue area: renderer Concerns our graphics renderer lang: c++ Done in C++ code bugfix Restores intended behavior labels May 18, 2025
@github-project-automation github-project-automation bot moved this to 📋 Backlog in openage renderer May 18, 2025
@Skosulor
Copy link
Author

Looks like its failing to set unform texture because it does not exist? GUI::initialize_render_pass:

	this->texture_unif = maptex_shader->new_uniform_input("texture", this->texture);

CleanShot 2025-05-19 at 12 18 38@2x

this->texture is confirmed to have been set so I do not know how to interpret the error.

@heinezen
Copy link
Member

heinezen commented May 19, 2025

@Skosulor The error refers to a uniform in the shader source code. What that basically means is: It tried to set a value for the uniform named "texture", but the GLSL source code does not have a uniform with that name.

Edit: The uniform is here in the GLSL code:

uniform sampler2D texture;

@heinezen
Copy link
Member

You might be able to upgrade the shader to OpenGL 3.3 with this code. I did not test this:

#version 330
// total basic standard texture drawing fragment shader

// the texture data
uniform sampler2D texture;

// interpolated texture coordinates received from vertex shader
in vec2 tex_position;
out vec4 col;

void main (void) {
	// this sets the fragment color to the corresponding texel.
	col = texture2D(texture, tex_position);
}

@Skosulor
Copy link
Author

You might be able to upgrade the shader to OpenGL 3.3 with this code. I did not test this:

#version 330
// total basic standard texture drawing fragment shader

// the texture data
uniform sampler2D texture;

// interpolated texture coordinates received from vertex shader
in vec2 tex_position;
out vec4 col;

void main (void) {
	// this sets the fragment color to the corresponding texel.
	col = texture2D(texture, tex_position);
}

I made it to:

#version 330 core

uniform sampler2D texture_;

in vec2 tex_position;
out vec4 frag_color;

void main(void) {
    frag_color = texture(texture_, tex_position);
}

So I changed it to texture_ too in the code so now I get even further! But maybe the shader should be as you have written it?

But now I get a new error but I do not think it is the shader anymore!

INFO [T2] Loading .nyan file: swgb_base/data/terrain/path4/path4.nyan
INFO [T2] Game simulation started
INFO Presenter: Graphics subsystems initialized
INFO Presenter: Initializing input subsystem...
INFO Loading game simulation controls
INFO Loading GUI controls
INFO Loading camera controls
INFO Loading HUD controls
INFO Presenter: Input subsystem initialized
INFO [T1] Time loop exited

SIGSEGV

FATAL: terminate has been called

current stack:


SIGSEGV
libc++abi: terminating
Traceback (most recent call last):
  File ?, in _pthread_start+0x88 [0x1a005c2e4]

@Skosulor
Copy link
Author

Hmm It seems a thread is trying to access a shared ptr that doesn't exist anymore

thread #6, stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
    frame #0: 0x00000001026e0f6c libopenage.0.dylib`std::__1::shared_ptr<openage::event::State>::shared_ptr[abi:ne200100]<openage::gamestate::GameState, 0>(this=0x00000001700b6ec0, __r=nullptr) at shared_ptr.h:479:87
    frame #1: 0x00000001026d95c0 libopenage.0.dylib`std::__1::shared_ptr<openage::event::State>::shared_ptr[abi:ne200100]<openage::gamestate::GameState, 0>(this=0x00000001700b6ec0, __r=nullptr) at shared_ptr.h:479:119
    frame #2: 0x00000001026d933c libopenage.0.dylib`openage::gamestate::GameSimulation::run(this=0x000000010c204098) at simulation.cpp:49:46
    frame #3: 0x00000001026237fc libopenage.0.dylib`openage::engine::Engine::loop_simulation(this=0x000000016fdfd898) at engine.cpp:84:20
    frame #4: 0x00000001026260e0 libopenage.0.dylib`openage::engine::Engine::loop()::$_0::operator()(this=0x0000600000b2cf98) const at engine.cpp:67:10
    frame #6: 0x000000010262606c libopenage.0.dylib`void std::__1::__thread_execute[abi:ne200100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::loop()::$_0>(__t=size=2, (null)=__tuple_indices<> @ 0x00000001700b6f7f) at thread.h:199:3
    frame #7: 0x0000000102625e84 libopenage.0.dylib`void* std::__1::__thread_proxy[abi:ne200100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, openage::engine::Engine::loop()::$_0>>(__vp=0x0000600000b2cf90) at thread.h:208:3

@heinezen
Copy link
Member

INFO [T1] Time loop exited
frame #2: 0x00000001026d933c libopenage.0.dylib`openage::gamestate::GameSimulation::run(this=0x000000010c204098) at simulation.cpp:49:46

Based on this line I think it's more likely that the time loop got destroyed somehow.

@Skosulor
Copy link
Author

INFO [T1] Time loop exited
frame #2: 0x00000001026d933c libopenage.0.dylib`openage::gamestate::GameSimulation::run(this=0x000000010c204098) at simulation.cpp:49:46

Based on this line I think it's more likely that the time loop got destroyed somehow.

It seems to happen because the destructor is called on most thread.

I have narrowd down the crash to:

			for (auto &cb : this->on_resize) {
				cb(width, height, this->scale_dpr);

in GlWindow::Update in window.cpp:126

@Skosulor
Copy link
Author

Eureka!

CleanShot 2025-05-19 at 17 13 15@2x

Had to update the name of texture in one more place :P

@Skosulor
Copy link
Author

Is the performance as seen in the GIF as expected from the current state of openage?

CleanShot 2025-05-19 at 20 11 29

@heinezen
Copy link
Member

Performance as in frames? :D You can test that with stresstest 0.

If the question is if that is how openage works in general, then yes, what you see looks like the correct state.

@Skosulor
Copy link
Author

Skosulor commented May 19, 2025

Performance as in frames? :D You can test that with stresstest 0.

If the question is if that is how openage works in general, then yes, what you see looks like the correct state.

Yeah, I meant as in frames :P

It seems I cant run it

CleanShot 2025-05-19 at 20 31 14@2x

@heinezen
Copy link
Member

Try this

cd bin && ./run test --demo renderer.tests.stresstest 0

@Skosulor
Copy link
Author

./run test --demo renderer.tests.stresstest 0

Same result:

CleanShot 2025-05-19 at 20 33 42@2x

@heinezen
Copy link
Member

Looks like the docs are wrong 🙈 This command should work:

cd bin && ./run test --demo renderer.tests.renderer_stresstest 0

@Skosulor
Copy link
Author

Looks like the docs are wrong 🙈 This command should work:

cd bin && ./run test --demo renderer.tests.renderer_stresstest 0

That went fine, 1-2k FPS ish. But when launching the "full game" I experience a lot of lag when moving around the camera and poor response when zooming in and out as seen in the gif above

@heinezen
Copy link
Member

Do the units move normally (i.e. are the animations smooth)?

@Skosulor
Copy link
Author

Do the units move normally (i.e. are the animations smooth)?

I have not figured out how to move them :P

@heinezen
Copy link
Member

Select them with the rectangle you draw with left mouse, then right click somewhere :D

@Skosulor
Copy link
Author

Select them with the rectangle you draw with left mouse, then right click somewhere :D

CleanShot 2025-05-19 at 21 39 43

The GIF is an accurate representation of how it looks for me

@Skosulor
Copy link
Author

But I think I'm done with the PR so it is ready for review now :)

@heinezen
Copy link
Member

I'm going to think about a few suggestion how to structure the code and then come back with a review :)

<< "(" << std::jthread::hardware_concurrency() << " available)");
}

void Engine::loop() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The structure with loop() and loop_simulation() is a bit too convoluted now I think. I recommend we organize this in a different way:

  1. Move all thread functions (time loop, simulation loop, presenter loop) into a separate function definition (maybe even outside Engine class?)
  2. Move the thread spawning to Engine::loop() (so that alll threads are started there)
  3. In Engine::loop() it should be much clearer why we are running different functions in the main thread depending on headless mode. The comments should explain that this is because of the Qt requirements.

Comment on lines +57 to +58
log::log(INFO << "Using " << this->threads.size() + 1 << " threads "
<< "(" << std::jthread::hardware_concurrency() << " available)");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number is now no longer correct because simulation/presenter are started later. That's why I made the recommendation to start all threads in loop() in the other comment.

Comment on lines +119 to +123
/**
* Window settings
*/
const renderer::window_settings window_settings;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably better to store them in the presenter class and pass them in the constructor.

@@ -87,7 +88,7 @@ void GUI::initialize_render_pass(size_t width,
resources::Texture2dInfo(width, height, resources::pixel_format::rgba8));
auto fbo = this->renderer->create_texture_target({output_texture});

this->texture_unif = maptex_shader->new_uniform_input("texture", this->texture);
this->texture_unif = maptex_shader->new_uniform_input(texture_, this->texture);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a static variable should not be necessary for new_uniform_input(..), since all other calls just pass an in-place string. You should just be able to pass the string without any problems.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a constexpr as "texture" was used in more than one place. IMO it is better to have a constexpr/define rather than a hardcoded value, especially if it is used in more than one place.

However if you rather want it hardcoded I will object to it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would agree in general, but for these WIP parts of the engine it's probably better to hardcode it for now. My reason would be that it then becomes more "visible" what is done with the shader until it's properly defined. For the more mature shaders, we have a solution that is similar to what you propose where we store the uniform ID and use that

/**
* Shader uniform IDs for setting uniform values.
*/
inline static uniform_id_t obj_world_position;
inline static uniform_id_t flip_x;
inline static uniform_id_t flip_y;
inline static uniform_id_t tex;
inline static uniform_id_t tile_params;
inline static uniform_id_t scale;
inline static uniform_id_t subtex_size;
inline static uniform_id_t anchor_offset;


// the texture data
uniform sampler2D texture;
uniform sampler2D texture_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better rename it tex than using underscores because that aligns with other shader source code definitions.

Suggested change
uniform sampler2D texture_;
uniform sampler2D tex;

// this sets the fragment color to the corresponding texel.
gl_FragColor = texture2D(texture, tex_position);
void main(void) {
frag_color = texture(texture_, tex_position);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
frag_color = texture(texture_, tex_position);
frag_color = texture(tex, tex_position);


void main(void) {
gl_Position = vertex_position;
gl_Position = vertex_position;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaik you don't need this statement since gl_Position by definition contains the current vertex position already. You can remove that line.

Suggested change
gl_Position = vertex_position;

Comment on lines +22 to +33
if (alpha == 0) {
col = tex_val;
discard;
return;
} else if (alpha == 254) {
col = vec4(1.0f, 0.0f, 0.0f, 1.0f);
} else if (alpha == 252) {
col = vec4(0.0f, 1.0f, 0.0f, 1.0f);
} else if (alpha == 250) {
col = vec4(0.0f, 0.0f, 1.0f, 1.0f);
} else {
col = tex_val;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switch statements should definitely work in this place, so I would revisit this shader once you have fixed all the other comments.

Comment on lines +14 to +22
if (alpha == 0) {
discard;
} else if (alpha == 254) {
col = vec4(1.0, 0.0, 0.0, 1.0);
} else if (alpha == 252) {
col = vec4(0.0, 1.0, 0.0, 1.0);
} else if (alpha == 250) {
col = vec4(0.0, 0.0, 1.0, 1.0);
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Comment on lines +14 to +22
if (alpha == 0) {
discard;
} else if (alpha == 254) {
col = vec4(1.0, 0.0, 0.0, 1.0);
} else if (alpha == 252) {
col = vec4(0.0, 1.0, 0.0, 1.0);
} else if (alpha == 250) {
col = vec4(0.0, 0.0, 1.0, 1.0);
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

@Skosulor
Copy link
Author

Skosulor commented May 21, 2025

Thanks! I will rework the PR according to your comments. Will be away for a few days so there might be no progress until next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: renderer Concerns our graphics renderer bugfix Restores intended behavior lang: c++ Done in C++ code os: macos macOS-specific issue
Projects
Status: 📋 Backlog
Development

Successfully merging this pull request may close these issues.

2 participants