Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Can GetEvent or sf::Input be called from another thread?  (Read 10043 times)

0 Members and 1 Guest are viewing this topic.

mercurio7891

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« on: December 29, 2010, 10:34:10 am »
Hi I was wondering if sf::Window::GetEvent or sf::Input be used from another thread from that of which the window is created?

for example
thread 1: Create the Window and do all rendering (aka Graphics Thread)
thread 2: Physics Thread
thread 3: Main Loop where I call window::GetEvent or use the sf::Input here?

is this possible??

regards

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #1 on: December 29, 2010, 10:38:18 am »
Nop, this is disallowed by the OS.

However, the following scenario works:
- thread 1: Create the Window and main Loop where you call window::GetEvent or use the sf::Input
- thread 2: Physics Thread
- thread 3: Graphics thread
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #2 on: December 29, 2010, 02:44:23 pm »
Quote from: "Laurent"
Nop, this is disallowed by the OS.

However, the following scenario works:
- thread 1: Create the Window and main Loop where you call window::GetEvent or use the sf::Input
- thread 2: Physics Thread
- thread 3: Graphics thread


That's how I designed my game engine for example :)
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« Reply #3 on: December 30, 2010, 01:15:16 am »
Question:

Wouldn't we get a more stable application if the main thread was the graphics thread? (Fetch events and render everything)

Have a renderer drawing all game structures in the main loop and those structures would be updated in some other thread : )

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #4 on: December 30, 2010, 01:27:26 am »
Depends on how you design it. The problem with having anything heavy together with the events is that the gamer can experience a delay in the input. For example in my game engine my rendering works at a maximum of 60Hz while my main thread works at a 1000Hz, so even if I would do something heavy in the rendering or logics threads, the input will always be the same and no delay will be felt by the gamer.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #5 on: December 30, 2010, 08:06:02 am »
Quote
The problem with having anything heavy together with the events is that the gamer can experience a delay in the input. For example in my game engine my rendering works at a maximum of 60Hz while my main thread works at a 1000Hz, so even if I would do something heavy in the rendering or logics threads, the input will always be the same and no delay will be felt by the gamer.

Is it really noticeable? I mean, even if you process events as fast as possible, their effect will still be seen only on the next graphics refresh, so isn't it the same as processing them directly before that refresh (ie. in the graphics loop)? I'm just curious, as I've never experienced such a design.
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #6 on: December 30, 2010, 02:57:17 pm »
Quote from: "Laurent"
Quote
The problem with having anything heavy together with the events is that the gamer can experience a delay in the input. For example in my game engine my rendering works at a maximum of 60Hz while my main thread works at a 1000Hz, so even if I would do something heavy in the rendering or logics threads, the input will always be the same and no delay will be felt by the gamer.

Is it really noticeable? I mean, even if you process events as fast as possible, their effect will still be seen only on the next graphics refresh, so isn't it the same as processing them directly before that refresh (ie. in the graphics loop)? I'm just curious, as I've never experienced such a design.


I am not a 100% sure. I'm basing it on that in my class there's a lot of hardcore gamers(Duuh... we want to make games) including me. And you do notice a difference in responsiveness between a game running at 120 FPS or 60 FPS even if you don't see any graphical difference.

I kind of try to exploit this in my engine since I have the main thread at 1000Hz, the logic threads at 1000Hz and finally the graphics at 120Hz. The engine is made completely asynchronous so the 3 threads will never have to wait for each other. And most of the time it will be that the event signals get processed directly in the main thread, converted to appropriate signals sent to the logics thread where any associated function/update will be performed. If this results in an entity get's moved for example then the renderer has to be notified and will be by a "Signal.Renderer.Entity.Moved" signal containing what entity and it's position. I believe this should give me an optimal way to have the best responsiveness even though graphics haven't caught up.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #7 on: December 30, 2010, 03:08:54 pm »
Ok I see. If the logic thread runs as fast as the event thread, it makes sense.
Laurent Gomila - SFML developer

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« Reply #8 on: December 31, 2010, 12:00:24 am »
Quote from: "Laurent"
Nop, this is disallowed by the OS.

However, the following scenario works:
- thread 1: Create the Window and main Loop where you call window::GetEvent or use the sf::Input
- thread 2: Physics Thread
- thread 3: Graphics thread

I'm really bad with threads and I'm having a bit of trouble trying to think of algorithm with this working (I'm a beginner).

Are there any examples of something simple? I searched the wiki out of curiosity but I couldn't find anything (or I'm just bad at searching).

Thanks :)

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #9 on: December 31, 2010, 12:21:43 am »
There isn't really anything simple. This is pretty heavy stuff. So only thing I can say is to experiment if you don't want to look at some more advanced and complete examples.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« Reply #10 on: December 31, 2010, 01:11:35 am »
I'd be willing to look at any example then  :)
I'm having trouble picturing threads.

I tried doing the following:
I have a simple class with some sprites...
(I trimmed the constructors, initializations, etc  to keep it short. Let's suppose all sf::Sprites have an image already set)
Code: [Select]

//App is a sf::RenderWindow object

class main_roll
{
public:
       sf::Sprite char1;
       void DrawStuff()
       {
                App.Clear();
                App.Draw(char1);
                App.Display();
       }
       void MainInputs()
       {
               //Get Inputs and Move char1
       }
       void MainRoll()
       {
              MainInputs();
              DrawStuff();
       }

};


And I wanted to make "DrawStuff" a thread.
I tried:

Code: [Select]

class main_roll
{
public:
       sf::Sprite char1;
       void DrawStuff()
       {
                App->Clear();
                App->Draw(char1);
                App->Display();
       }
       void MainInputs(void *Data)
       {
               //Get Inputs and Move char1
       }
       void MainRoll()
       {
              sf::Thread th(&DrawStuff);
              th.Launch();
              MainInputs();
       }

};


But it seems it's not the correct way to do it.
So as you can see I'm pretty bad. But I'm willing to look at any example.

Thanks again :)

(Hope this isn't considered topic-hijacking)

Wafthrudnir

  • Newbie
  • *
  • Posts: 26
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« Reply #11 on: December 31, 2010, 01:24:01 am »
I am a lil drunk atm, but i try to add some stuff ;D

Is it possible to make a thread via a Class Method in SFML?!?...try this:

You need a wrapper function for each Class Method to use in a thread.

E.G.

For CLASS.Method1() you must run this function in a thread:

Code: [Select]
void meth1func(CLASS* c)
{
    c->Method1();
}


So the Thread should be working...if that's your problem...

If not, i could take a look at some source i wrote a while ago and give an exact example....

regards,

Wafthrudnir

P.S: I always used WinApi Threads...not the SFML ones...[/code]
Black Metal + Coding = Win!

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« Reply #12 on: December 31, 2010, 03:27:36 am »
I'm having a bit of trouble understanding that example.
What does CLASS mean? Is it creating an object of "main_roll" on my example?

Sorry for the trouble  :(

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Can GetEvent or sf::Input be called from another thread?
« Reply #13 on: December 31, 2010, 05:29:58 am »
The simplest way to do this is that at the end of each threads frequency stop(when the thread is finished working and are about to sleep) it waits for the other threads to catchup, and then synchronize. So let's say we have the Main thread which should monitor and handle the other threads, we also put the event-pulling into this thread. Then we have the logics thread and the rendering thread.

At the start of each cycle the main thread will pass along copies of the processed events to the input and render queue that it needs to. Each thread does it's work. Render, calculate collisions, process events. And when done it goes to sleep and waits until the main thread tells everyone "BACK TO WORK YOU LAZY ***" and a new cycle begins. But before main tells the threads to go back to work, main should copy all data in the logics thread over to the rendering thread. It's very important that every thread woks in it's own environment, we never want the threads to work with shared data at the same time.

This is the simplest way I can come up with to implement a way for threads to be assigned specific subsystem-roles. I.E: One rendering thread, One logics thread and so on. Now this way got a lot of cons. Like the rendering will always be 1 frame behind the logics, the fact that we have to duplicate data(we would have to anyway if we want to make it efficient), that the data is copied at every frame is not a good choice. And so on. The pro is(according to my teachers, I haven't tried this model) that it will actually run faster on a 2+ Core platform if done properly. Also it's probably the easiest way in getting into this kind of thinking.

I can go more deeper into detail if this wasn't enough. I can also give you another model which I talked a little about in some previous posts. I am currently using it in my game engine which makes it completely asynchronous. Every part, every thread is independent from one another. But if I'm gonna go trough that I'll have to write a whole essay and probably draw diagrams to explain it. Though a part of that system is available in the wiki ^^

It's one thing to have it in your head another to try and explain it to someone else.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Wafthrudnir

  • Newbie
  • *
  • Posts: 26
    • View Profile
Can GetEvent or sf::Input be called from another thread?
« Reply #14 on: December 31, 2010, 05:33:13 am »
Hi,

sorry maybe it's the alcohol ;D I try it this way:

With the WinApi it's like this

You have a class called MyClass...

Code: [Select]

class MyClass
{
   public:
       void drawGraphics();
};


This class has the method drawGraphics()...

You can not run this method in a thread. A thread needs to be a real function.
If you want to use this method as a thread method, there is this workaround:
You build a (global) function that takes a pointer of an object of your class(MyClass)
Like:

Code: [Select]

void wrapperDrawGraphics(MyClass* c )
{
      c->drawGraphics()
}


When creating a thread in WinApi style it would look like this:

Code: [Select]

MyClass myClassObject;
DWORD dwThreadId;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wrapperDrawGraphics, myClassObject, 0, &dwThreadId);


I do not know if SFML is handling it different, but maybe creating this kind of helper function, that takes a pointer to your class Object and running this function in a thread would help?!!

in SFML it would look like this i think:

Code: [Select]

class MyClass
{
   public:
       void drawGraphics();
};

void wrapperDrawGraphics(void* c)
{
     MyClass* myClassObj = static_cast<MyClass*>(c); //cast back to MyClass
     myClassObj->drawGraphics();
}

//somewhere in main maybe...
MyClass myClassObject;
//First the function to be run in a thread, then the param passed to this function...
sf::Thread Thread(&wrapperDrawGraphics, &myClassObject);
Thread.Launch();


This would make the wrapperDrawGraphics function run in a thread. And cuz this function calls the drawGraphics-Method of the referenced MyClass object, the Method is running in a thread.

Hope this helps somehow.

Regards,

Wafthrudnir
Black Metal + Coding = Win!