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
feat(reactor): make separate graphic scheduler/thread #4865
base: develop
Are you sure you want to change the base?
Conversation
* splash screen's loop handles by Flux/Mono * Most calls to GL/GLFW runs at Graphic Thread via GameScheduler#runBlockingGraphics.
…gerSubsystem' into refactor/remove-usage-ThreadManagerSubsystem
TeraED was broken before this PR :( |
* remove unused code
I did run I could not really play it as I was at 0.6 fps, but that might be related to too much load on my machine...
What do you mean by that? I haven't tried to start TeraED for ages, but it at least compiled just fine when running |
TeraED hardcrashes with many nullpointers during initializing MainMenuState. This errors not related with rendering code.
Hmm. Which gpu are you using?
Sounds familiar. With red rectangle. I will google it. |
Ok. Splashscreen Rendering issues at macos should be resolved at splashscreen repo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an interesting idea, but seeing it in practice is scary
I think a lot of what I'm seeing is a byproduct of the fact that this is wrapping a lot of stuff in the runBlockingGraphics
scheduler to keep it as close as possible to the existing implementation, which is arguably the right way to get something like this done in an incremental way.
but so much blocking
and so much confusion about "do I need to wrap this in runGraphics
, or is the method I'm calling going to do that?"
public static <T> Flux<T> wrapActivity(Scheduler scheduler, String name, Flux<T> mono) { | ||
return Flux.using( | ||
() -> ThreadMonitor.startThreadActivity(name), | ||
activity -> mono, | ||
ThreadActivity::close |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I convinced myself this works for a Runnable turned in to a Mono, because we know the Runnable will execute and be on that thread until it is done, and then the mono is over.
Flux is less clear. There could be lots of time between events. Do we report that as all one thread activity?
also, other stuff could be running on that thread between the events of that Flux, is that going to mess up the assumptions in the ThreadMonitor implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch.
Needs to handle both cases.
Whole flux as thread activity and element of flux as thread activity.
Tasks that running at graphic scheduler works via fifo queue (see threadcapturedscheduler)
Then no one switching during processing.
} | ||
|
||
/** | ||
* Wraps {@link Mono} with activity monitor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
if (!graphicsScheduler.isSchedulerThread(Thread.currentThread())) { | ||
mono = mono | ||
.doOnSubscribe(s-> GLFW.glfwMakeContextCurrent(LwjglGraphics.windowId)) | ||
.doFinally(f -> GLFW.glfwMakeContextCurrent(MemoryUtil.NULL)) | ||
.subscribeOn(graphicsScheduler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not experienced with multithreaded use of GL, so I Am Not An Expert, but I've read like 1.2 papers on it, and I am a little worried about making much use of glfwMakeContextCurrent
. I hear the context-switching is generally not worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There required for handling multiple contexts/windows.
At linux and windows you can use separate threads for handling separate gl contexts (like window/cintext per thread)
At macos - not.
Then you should change context i this way.
Splashscreen... (You can see some screenshots with messing gl contexts at #architecture)
.doFinally(f -> GLFW.glfwMakeContextCurrent(MemoryUtil.NULL)) | ||
.subscribeOn(graphicsScheduler); | ||
} | ||
return mono.block(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a blocking API for this? I didn't think GL calls were synchronous or had return values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some graphics monos load assets and may corrupt state(concurrent access) in theory.
Another. This places was design and tested to run in sequence
I choose fail safe path then for now
return GameScheduler.runBlockingGraphics("hasFocus", | ||
() -> GLFW.GLFW_TRUE == GLFW.glfwGetWindowAttrib(GLFW.glfwGetCurrentContext(), GLFW.GLFW_FOCUSED)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, here's that blocking use case I was asking about.
bother, this API is a mashup of things, as some of them are about the GL context, and other things (like focus) are not part of the GL API at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, I don't think these methods that wrap a single glfw function are worth using GameScheduler.wrapActivity on. They shouldn't take enough time to be worth clocking, and, well, they block the graphics thread, so we're not going to be seeing those as open tasks on any monitor that renders via the graphics thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glfw related to context too.
Gl context = glfw window handle.
Rules about gl context at one thread applicable for glfw partially (and there i takes context from static. There needs a refactoring to stores context/window handle and reuse it)
GameScheduler.runBlockingGraphics("isFullscreen", () -> | ||
glViewport(0, 0, width, height) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cut/paste error in description
@@ -46,16 +42,9 @@ | |||
import static org.lwjgl.opengl.GL11.glGenTextures; | |||
import static org.lwjgl.opengl.GL11.glTexParameterf; | |||
|
|||
public class LwjglGraphicsManager implements LwjglGraphicsProcessing { | |||
|
|||
private final BlockingDeque<Runnable> displayThreadActions = Queues.newLinkedBlockingDeque(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already had a queue of display thread actions? HMM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See main of terasology.
And ThreadCapturedScheduler.
asynchToDisplayThread(() -> { | ||
int id = glGenTextures(); | ||
reloadTexture2D(id, buffers, wrapMode, filterMode, width, height); | ||
idConsumer.accept(id); | ||
}); | ||
int id = glGenTextures(); | ||
reloadTexture2D(id, buffers, wrapMode, filterMode, width, height); | ||
idConsumer.accept(id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these methods lost their async wrappers? why did createTexture3D
keep it but not this createTexture2D
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think about this methods like this.
Textures3d runs in graphics now (doReload)
Textures2d do same already.
Needs to revisit this place later
Renderer renderer = Mono.just(0) | ||
.subscribeOn(GameScheduler.graphics()) | ||
.doOnNext(n -> initWindow()) | ||
.map((n) -> new Renderer()) | ||
.doOnNext(Renderer::init) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starting this with just(0)
instead of initWindow
feels weird. Is that so you have something to subscribeOn
? Is this the sort of thing that publishOn
is for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I detected mono.fromRunable method too late.
All methods used there should runs at graphics.
facades/PC/src/main/java/org/terasology/engine/GLFWSplashScreen.java
Outdated
Show resolved
Hide resolved
…t/add-graphics-scheduler
@skaldarnar |
# Conflicts: # engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkMesh.java
…scheduler # Conflicts: # engine/src/main/java/org/terasology/engine/core/subsystem/lwjgl/LwjglDisplayDevice.java # engine/src/main/java/org/terasology/engine/core/subsystem/lwjgl/LwjglGraphics.java
Now I get the following error about my Mac not being able to support the required OpenGL version (I think that's what
However,
Edit: Seems related to MC-153714, siumilar error and similar/same detected version This question on StackOverflow suggests to replace your code from |
@skaldarnar |
The changes seem to help a bit, but it's still not working on (my) Mac 😕 The splash screen window appears before startup, but is rendered as flickering red triangle. No images or text are shown. I did check this with the MovingBlocks/SplashScreen#7 by doing the following, did not help - do I need to set up/configure anything else?
Eventually, the main menu shows up, but when I try to start/create a world the game crashes before anything is rendered on screen with the following error. The loading bar reaches the end and is "Catching World", it looks like it crashes right before rendering the first in-game frame...
|
Contains
Ref: Add specific macos flags for window creating SplashScreen#7 has macos specific flags for macos (should helps with macos glitches like red window, wring dpi)
How to test
3.1. block digging particles
3.2. different Overlay renderer.
Outstanding before merging
After merge: