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

Author Topic: Problem with sf::RenderTexture & std::future  (Read 2388 times)

0 Members and 1 Guest are viewing this topic.

GetterSetter

  • Newbie
  • *
  • Posts: 18
    • View Profile
Problem with sf::RenderTexture & std::future
« on: March 18, 2020, 10:54:10 pm »
Hi, I want to render objects in another thread. I can do this with RenderWindow, but can't with RenderTexture. My window and a mouse cursor freeze and blink when I start my program. It happens when I use std::future, but if I don't, it works fine.
Code:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <vector>
#include <string>
#include "RoundedRectangleShape.hpp"
#include "Entity.hpp"
#include <future>
 
#ifdef __linux__
#include <X11/Xlib.h>
#endif
 
 
void render(sf::RenderTarget &target, const std::vector<sf::Drawable *> &objects, sf::RenderStates states = sf::RenderStates{})
{
    #ifdef __linux__
    XInitThreads();
    #endif
    target.clear();
    for(auto &el : objects)
    {
        target.draw(*el, states);
    }
}
 
 
int main()
{
    #ifdef __linux__
    XInitThreads();
    #endif
 
    sf::Texture texture_2;
    texture_2.loadFromFile("img.jpg");
 
    sf::RenderWindow window{sf::VideoMode{800,600}, "window"};
 
    sf::RectangleShape scene;
   
 
    std::vector<sf::Drawable *> objects;
   
    sf::RoundedRectangleShape main{sf::Vector2f{600,300},10,30},
                              login{sf::Vector2f{450,50},10,30},
                              password{sf::Vector2f{450,50},10,30};
 
    main.setOrigin(300,150);
    login.setOrigin(225,75);
    password.setOrigin(225,-25);
 
 
    main.setOutlineColor(sf::Color::Red);
    main.setOutlineThickness(8);
 
    login.setFillColor(sf::Color(201,201,201,200));
    password.setFillColor(sf::Color(201,201,201,200));
   
    Entity entity;
    entity.setEntities(&main, &login, &password);
 
    objects.emplace_back(&entity);
 
    sf::RenderTexture texture;
 
    texture.create(8000,6000);
    texture.setActive(false);
 
    entity.setScale(10,10);
 
    sf::View visibleArea{sf::FloatRect{0.f, 0.f, 800,600}};
 
    while (window.isOpen())
    {
       
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
             
            if (event.type == sf::Event::Resized)
            {
                float width, height;
                width = event.size.width;
                height = event.size.height;
 
                entity.setPosition(sf::Vector2f{texture.getSize()}/2.f);
       
                visibleArea.reset(sf::FloatRect{0.f, 0.f, width,height});
                visibleArea.setCenter(sf::Vector2f{width, height}/2.f);
 
                scene.setSize(sf::Vector2f{width, width*6.f/8.f});
                if(height>=scene.getSize().y)
                   scene.setSize(sf::Vector2f{height*8.f/6.f, height});
               
                scene.setScale(1.03,1.03);
                scene.setOrigin(scene.getSize()/2.f);
                scene.setPosition(visibleArea.getCenter());
 
                window.setView(visibleArea);
               
            }    
        }
 
       
 
       
        std::future rendering = std::async(std::launch::async, render, std::ref(texture), std::ref(objects), sf::RenderStates{});
       
        //Something
 
        rendering.get();
               
        texture.display();
 
        scene.setTexture(&texture.getTexture(),true);
 
        window.clear();
        window.draw(scene);    
        window.display();
       
    }
 
    return 0;
}
 

And the video: https://streamable.com/r3qoi
« Last Edit: March 18, 2020, 10:56:19 pm by GetterSetter »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Problem with sf::RenderTexture & std::future
« Reply #1 on: March 19, 2020, 08:45:33 am »
Hi

You should read this if not already done: https://www.sfml-dev.org/tutorials/2.5/window-opengl.php#rendering-from-threads

And I don't know what you're trying to achieve, but it looks like a bad idea ;)
Laurent Gomila - SFML developer

GetterSetter

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: Problem with sf::RenderTexture & std::future
« Reply #2 on: March 19, 2020, 09:05:45 am »
Hi

You should read this if not already done: https://www.sfml-dev.org/tutorials/2.5/window-opengl.php#rendering-from-threads

And I don't know what you're trying to achieve, but it looks like a bad idea ;)

I have already done. I rewrote render(...), but it didn't help:
void render(sf::RenderTarget &target, const std::vector<sf::Drawable *> &objects, sf::RenderStates states = sf::RenderStates{})
{
    #ifdef __linux__
    XInitThreads();
    #endif
    target.setActive(true);
    target.clear();
    for(auto &el : objects)
    {
        target.draw(*el, states);
    }
    target.setActive(false);
}
 
Why does it look like a bad idea? I just want to render objects in another thread while doing something else, so that I decided to use std::future, because I don't like using mutexes.
« Last Edit: March 19, 2020, 02:57:01 pm by GetterSetter »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Problem with sf::RenderTexture & std::future
« Reply #3 on: March 19, 2020, 10:47:57 am »
What's important is to call setActive(false) in the thread where it is active (the main one), before using it in another thread. Note that you don't need an explicit call to setActive(true) as long as you're only using the sfml-graphics API (it's done implicitly); it's required only for direct OpenGL calls.

Quote
Why it looks like a bad idea? I just want to render objects in another thread while doing something else
Rendering doesn't take long. The OpenGL driver usually alreayd queues operations to perform them asynchronously, so most of the graphics calls return immediately. What takes time in an app is often the various computations needed to update the geometry and state of entities, not the rendering itself. Drawing commands are usually kept in a single thread.

Quote
I decided to use std::future, because I don't like using mutexes
That's not the same thing ;)
Laurent Gomila - SFML developer

GetterSetter

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: Problem with sf::RenderTexture & std::future
« Reply #4 on: March 19, 2020, 02:56:21 pm »
Thanks a lot, I thought that rendering is a long and difficult task.

But why does my code work well with RenderWindow?

That's not the same thing ;)
I meant that I don't like working with mutexes when I use std::thread


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Problem with sf::RenderTexture & std::future
« Reply #5 on: March 19, 2020, 03:30:12 pm »
Quote
Thanks a lot, I thought that rendering is a long and difficult task.
Mainly done on the GPU while the CPU is doing something else.

Quote
But why does my code work well with RenderWindow?
No idea.
Laurent Gomila - SFML developer