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

Author Topic: Flipped RenderTexture  (Read 11211 times)

0 Members and 1 Guest are viewing this topic.

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« on: January 29, 2012, 04:41:38 am »
I am pretty sure we discussed this somewhere but I couldn't find it when searching for it.

Well anyway the resulting texture from a RenderTexture is flipped in the Y-coordinate. Right and I thought I could just do a flip of the sprite that I worked with.... but that functionality is long gone so how do I solve it? xD
Negative scaling is still not available right?
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

pdinklag

  • Sr. Member
  • ****
  • Posts: 330
  • JSFML Developer
    • View Profile
    • JSFML Website
Flipped RenderTexture
« Reply #1 on: January 29, 2012, 04:51:15 am »
You need to call Display() before actually using it, I had the same problem before. ;)
JSFML - The Java binding to SFML.

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #2 on: January 29, 2012, 05:10:16 am »
I am calling display on it before using it. Though I am rendering on it from a different thread. But you are only allowed access to the texture when the thread is done so display has been called.

I'll see if I can narrow it down a little more.

UPDATE: Happens with the most simple test case as well.

UPDATE: Damn lol I jsut noticed that I forgot to call display and if I do it works xD But still doesn't explain why it doesn't work in my threaded example.. I'll see if I did some stupid mistake instead.

Hmmm this is weird.. Magically it works... I did not change the code in any way.. just did a rebuild of the entire project and that solved it for me.... Darn it...
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Flipped RenderTexture
« Reply #3 on: January 29, 2012, 09:19:03 am »
Quote
Negative scaling is still not available right?

It is.
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #4 on: January 29, 2012, 07:00:37 pm »
Actually I saw a very weird behaviour. If I don't call "Display" in the main thread I get the texture flipped actually. But if I do then everything works just like it is expected.

Is this a bug I should write in the issue tracker?
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Flipped RenderTexture
« Reply #5 on: January 29, 2012, 07:11:00 pm »
Quote
Is this a bug I should write in the issue tracker?

You should first show me a minimal code that reproduces this problem.
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #6 on: January 29, 2012, 07:36:42 pm »
Code: [Select]
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

struct Synchronizer
{
    sf::RenderTexture* texture;
    bool isAllowedToRun;
    bool isWorking;
    bool isAllowedToStart;
};

void ThreadedRender( Synchronizer* aSynchronizer )
{
    aSynchronizer->texture->SetActive( true );
    sf::Text text( "Hello World!" );
    while( aSynchronizer->isAllowedToRun == true )
    {
        if( aSynchronizer->isAllowedToStart == true )
        {
            aSynchronizer->isWorking = true;
            aSynchronizer->isAllowedToStart = false;

            aSynchronizer->texture->Clear( sf::Color::Red );
            aSynchronizer->texture->Draw( text );
            aSynchronizer->texture->Display();

            aSynchronizer->isWorking = false;
        }
    }
    aSynchronizer->texture->SetActive( false );
}

void WaitForSynch( Synchronizer* aSynchronizer )
{
    while( aSynchronizer->isWorking == true || aSynchronizer->isAllowedToStart == true )
    {
        sf::Sleep( sf::Milliseconds( 1 ) );
    }
}

void CompleteSynch( Synchronizer* aSynchronzier )
{
    aSynchronzier->isAllowedToStart = true;
}

void ExitSynch( Synchronizer* aSynchronizer )
{
    aSynchronizer->isAllowedToRun = false;
}

int main()
{
    sf::ContextSettings settings;
    settings.MajorVersion = 3;
    settings.MinorVersion = 0;

    sf::RenderWindow window( sf::VideoMode( 800, 600 ), "Renderer", sf::Style::Default, settings );
    sf::RenderTexture scene;
    scene.Create( 800, 600, true );
    //scene.Display();   /
    scene.SetActive( false );

    Synchronizer *synchronizer = new Synchronizer();
    synchronizer->texture = &scene;
    synchronizer->isAllowedToRun = true;
    synchronizer->isAllowedToStart = false;
    synchronizer->isWorking = false;

    sf::Thread renderer( ThreadedRender, synchronizer );
    renderer.Launch();

    while( window.IsOpen() == true )
    {
        WaitForSynch( synchronizer );
        sf::Sprite sprite( scene.GetTexture() );
        window.Draw( sprite );
        window.Display();
        CompleteSynch( synchronizer );
       
        sf::Event event;
        while( window.PollEvent( event ) == true )
        {
            if( event.Type == sf::Event::Closed )
            {
                    window.Close();
                    break;
            }
        }
    }
    ExitSynch( synchronizer );
    return 0;
}


Quick question, what happens if I give microseconds to sleep? It will still conform to 1 millisecond since that's the lowest resolution the OS gives right? You should really give us a sf::Yield function ^^
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Flipped RenderTexture
« Reply #7 on: January 29, 2012, 07:44:00 pm »
Quote
Quick question, what happens if I give microseconds to sleep? It will still conform to 1 millisecond since that's the lowest resolution the OS gives right?

Linux can use microseconds (at least the API allows it), on Windows it's milliseconds.

Quote
You should really give us a sf::Yield function

sf::Sleep(0) is usually enough. What you need here is a more powerful synchronization primitive (a wait condition).

I'll test your code as soon as I can.
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #8 on: January 29, 2012, 07:58:02 pm »
Quote from: "Laurent"
sf::Sleep(0) is usually enough. What you need here is a more powerful synchronization primitive (a wait condition).
Actually giving sf::Sleep(0) can break on the windows platform under special scenarios and give deadlocks or thread starvation problems. So no it's not acceptable. I've faced it several times and I have in some cases even gotten performance boost by increasing the sleep time to 1 millisecond. I've seen the behaviour on XP, Vista and 7.
Some of the problems are even described on MSDN.

What kind of synchronization primitive are you talking about? I just simplified my renderer and I only want it to return the texture when a frame is done. Do you have a better idea than what I currently have? If that's the case then I certainly want to hear it. The basic idea I have is to create several renderers at the same time. For Deferred rendering I can render several buffers at the same time and combine them together in the end giving me a lot of possibilities with this design ;)

Also do you have any statistics on the speed of copying a texture? I'm thinking like instead of synchronizing on the "GetTexture" function I can have that at synchronization that I copy the texture onto a texture that is always readable. Or maybe I should do this double buffered? Probably a better design.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #9 on: January 29, 2012, 10:13:40 pm »
I also observed something else that doesn't seem to work with textures. I tried with copying the texture and it seem to only be able to copy the texture once. I don't know if this is a threaded problem or just something wrong in the Texture implementation but it appeared when I expanded my threaded example. I even added an output to show that both the threads is still running and updating the texture.

Code: [Select]
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <sstream>
#include <iostream>

struct Synchronizer
{
    sf::RenderTexture* texture;
    bool isAllowedToRun;
    bool isWorking;
    bool isAllowedToStart;
};

unsigned int frame = 0;
void ThreadedRender( Synchronizer* aSynchronizer )
{
    aSynchronizer->texture->SetActive( true );
    sf::Text text( "Hello World!" );
    while( aSynchronizer->isAllowedToRun == true )
    {
        if( aSynchronizer->isAllowedToStart == true )
        {
            aSynchronizer->isWorking = true;
            aSynchronizer->isAllowedToStart = false;

            aSynchronizer->texture->Clear( sf::Color::Red );
            frame++;
            std::stringstream stream;
            stream << frame;
            text.SetString( stream.str() );
            aSynchronizer->texture->Draw( text );
            aSynchronizer->texture->Display();

            aSynchronizer->isWorking = false;
        }
    }
    aSynchronizer->texture->SetActive( false );
}

void WaitForSynch( Synchronizer* aSynchronizer )
{
    while( aSynchronizer->isWorking == true || aSynchronizer->isAllowedToStart == true )
    {
        sf::Sleep( sf::Milliseconds( 1 ) );
    }
}

void CompleteSynch( Synchronizer* aSynchronzier )
{
    aSynchronzier->isAllowedToStart = true;
}

void ExitSynch( Synchronizer* aSynchronizer )
{
    aSynchronizer->isAllowedToRun = false;
}

int main()
{
    sf::ContextSettings settings;
    settings.MajorVersion = 3;
    settings.MinorVersion = 0;

    sf::RenderWindow window( sf::VideoMode( 800, 600 ), "Renderer", sf::Style::Default, settings );
    sf::RenderTexture scene;
    scene.Create( 800, 600, true );
    scene.Display();
    scene.SetActive( false );

    Synchronizer *synchronizer = new Synchronizer();
    synchronizer->texture = &scene;
    synchronizer->isAllowedToRun = true;
    synchronizer->isAllowedToStart = false;
    synchronizer->isWorking = false;

    sf::Thread renderer( ThreadedRender, synchronizer );
    renderer.Launch();

    sf::Texture texture;

    while( window.IsOpen() == true )
    {
        WaitForSynch( synchronizer );
        texture = synchronizer->texture->GetTexture();
        sf::Sprite sprite( texture );
        window.Draw( sprite );
        window.Display();
        CompleteSynch( synchronizer );

        std::cout << frame << std::endl;

        sf::Event event;
        while( window.PollEvent( event ) == true )
        {
            if( event.Type == sf::Event::Closed )
            {
                    window.Close();
                    break;
            }
        }
    }
    ExitSynch( synchronizer );
    return 0;
}


You must be thinking right now: "DAMN THAT GROOGY DESTROYING MY CODE!" :P
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Flipped RenderTexture
« Reply #10 on: January 29, 2012, 10:20:19 pm »
Quote
Actually giving sf::Sleep(0) can break on the windows platform under special scenarios and give deadlocks or thread starvation problems.

That's good to hear.

Quote
What kind of synchronization primitive are you talking about?

When you want a thread to block until a flag is set by another thread, you need a wait condition. A while loop with sleep is an inefficient workaround. I have no idea if it applies to your design, or if it's just your example.

Quote
Also do you have any statistics on the speed of copying a texture?

Nop. And I haven't investigated your example yet so I cannot give you my opinion now ;)

About your texture problems: one thing that I've learnt is that sometimes you need an explicit glFlush after uploading texture data if you want other threads to see the update immediately.
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #11 on: January 29, 2012, 10:34:29 pm »
Quote from: "Laurent"
That's good to hear.
Thank my teacher, he's the one that told me... I didn't believe him.. Then I spent an entire night tracking down the bug. Great spending time on that when you are to leave in the project for producer estimation 9 o'clock in the morning.

Quote from: "Laurent"
When you want a thread to block until a flag is set by another thread, you need a wait condition. A while loop with sleep is an inefficient workaround. I have no idea if it applies to your design, or if it's just your example.
Hmm well I'll get to that point when I need it. The renderer will be aimed specifically for use together with rbSFML(That's why threading here is important, trying to avoid the GIL).

Quote from: "Laurent"
About your texture problems: one thing that I've learnt is that sometimes you need an explicit glFlush after uploading texture data if you want other threads to see the update immediately.

I tried placing out some flushes but got no improvement. It still displays only the first original texture. I wasn't planning on using this design but I just wanted to compare this against using a blocking reference(how I do in the first example) and compare it also against double buffered.

Actually getting quite off-topic here. Should I create a new thread?

NOTE: Verified that it's based on the texture is rendered in a separate thread. Did the same thing with a single thread and it behaved like intended.

Fun fact: I tried out my engine with simple drawings in debug mode on my university computer.... Got 4 000+ FPS on that machine... And the CPU is not maxed out, did you complete the OpenGL call optimizations yet? In any case it's damn fast :D This computer only went for around ~800 Euro. If you haven't then I really want to know what I'll get after that commit. I should start writing out the frame/update time instead of FPS if it's at these speeds. Should look much more stable.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Flipped RenderTexture
« Reply #12 on: January 30, 2012, 09:42:08 am »
Just as an aside, the C++11 standard library comes with an advanced threading API. Maybe some parts of it are helpful.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Flipped RenderTexture
« Reply #13 on: February 02, 2012, 12:04:33 am »
Hmm there might be an entire issue with the whole OpenGL and threading with SFML2 actually.. Even glew messes out in the second thread if I don't explicitly handles the problem.

Should probably try to fix these issues after SFML 2 has been released. As there seems to be a lot of holes.

For instance here is a new problem:
Code: [Select]
void ym::OpenGL::RendererImplementation::Initialize()
{
    myTarget.SetActive( true );
    /* Code... */
}


This fails for me really. This function is called in the rendering thread and more or less prepares the render texture(myTarget) to be rendered on. Any feature that actually requires glew to be initiated fails. And still sf::Shader::IsAvailable returns true which is weird. And yes the target has been set to not be active in the main thread.

And here's some more stuff I tested, putting glewInit before SetActive dpes nothing which is of course kind of obvious. But setting glewInit afterwards actually solves this problem. I don't know if they solve all problem discussed here:
Code: [Select]
void ym::OpenGL::RendererImplementation::Initialize()
{
    glewInit() // <- Doesn't help
    myTarget.SetActive( true );
    glewInit(); // <- Does help!
    /* Code... */
}


I would say that SFML2 is not safe for parallel environments yet considering all the problems I've found but with some quick dirty fixes you can get it to work just fine so I don't see a reason to hold up SFML2 development for this.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Silvah

  • Guest
Flipped RenderTexture
« Reply #14 on: February 02, 2012, 01:33:24 pm »
Quote from: "Groogy"
Actually giving sf::Sleep(0) can break on the windows platform under special scenarios and give deadlocks or thread starvation problems.
No wonder, yielding is a nice method to provoke all the Heisenbugs related to threading into revealing themselves. In working code, it's harmless. In buggy code, it helps you realizing that the bugs are there. So what's the problem?

And, uhm, the behavior of Sleep(0) is actually well-defined, so if you want something else, then you shouldn't blame Sleep(0) for that.

Quote from: "Groogy"
Some of the problems are even described on MSDN.
Any chance of getting a link?

 

anything