SFML community forums

Help => Graphics => Topic started by: GetterSetter on March 18, 2020, 10:54:10 pm

Title: Problem with sf::RenderTexture & std::future
Post by: GetterSetter 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
Title: Re: Problem with sf::RenderTexture & std::future
Post by: Laurent 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 ;)
Title: Re: Problem with sf::RenderTexture & std::future
Post by: GetterSetter 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.
Title: Re: Problem with sf::RenderTexture & std::future
Post by: Laurent 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 ;)
Title: Re: Problem with sf::RenderTexture & std::future
Post by: GetterSetter 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

Title: Re: Problem with sf::RenderTexture & std::future
Post by: Laurent 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.