SFML/SFML

[2.6.1] Drawing to RenderTexture "fails" after Texture copied from (Windows)

frayien opened this issue ยท 3 comments

Prerequisite Checklist

Describe your issue here

When you take the Texture of a RenderTexture by copy, subsequent draw to the RenderTexture will result in no color (black).
basic example is Code (1),
notice the copy sf::Texture tex = rtex.getTexture();
It is worth noting that the first frame ever is rendered correctly.

(The same happen if you take the code example from sf::RenderTexture Class Reference and replace sf::Sprite sprite(texture.getTexture()); with sf::Texture tex = texture.getTexture(); sf::Sprite sprite(tex);)

Due to how sf::RenderTexture Class Reference is ilustrated, Code (1) should be expected to work.

Observations :

  • Works on Ubuntu 22.04 LTS
  • Code (2) taking Texture by reference works.
  • not calling win.draw(sprite) make it work (using tex.copyToImage().saveToFile("tmp/fig" + std::to_string(i++) + ".png"); to see the texture content)

I messed around with setActive to try some things, but honestly I dont really know how OpenGL contexts work, and to cite the doc "you shouldn't care about it if you're not doing direct OpenGL stuff" but hey, it also states "Only one context can be current in a thread".

  • Code (3) calling setActive everywhere make it work.
  • Code (4) not calling window.setActive(false) make it not work. (which is weird because "Activating a render target will automatically deactivate the previously active context (if any)")

Your Environment

  • OS / distro / window manager: Windows 10 22H2
  • GPU : AMD Radeon RX Vega 64; pilot version : 23.10.23.02-230720a-394441C-AMD-Software-Adrenalin-Edition; Windows AMD pilot version : 31.0.21023.2012; OpenGL API Version 4.6; OpenGL Driver Version 23.07.230531_53c0013
  • SFML version: 2.6.1
  • Compiler / toolchain: cmake 3.27.6 gcc 13.0.1 x86_64-w64-mingw32 (mingw 64) / MSVC 19.29.30145.0
  • Special compiler / CMake flags: (SFML built with FetchContent)
    • set(CMAKE_CXX_STANDARD 23)
    • set(CMAKE_CXX_EXTENSIONS OFF)
    • set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
    • set(CMAKE_CXX_FLAGS "-Wall -Wextra")
    • set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
    • set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g1")
    • set(BUILD_SHARED_LIBS OFF)
    • set(SFML_BUILD_EXAMPLES OFF)
    • set(SFML_BUILD_DOC OFF)
    • set(SFML_BUILD_NETWORK OFF)
    • set(SFML_BUILD_AUDIO ON)
    • set(SFML_BUILD_GRAPHICS ON)
    • set(SFML_BUILD_WINDOW ON)
    • target_link_libraries(${PROJECT_NAME} sfml-graphics sfml-window sfml-system sfml-audio)

Steps to reproduce

  1. Draw to the RenderTexture
  2. Take the result Texture by copy
  3. Assign it to a Sprite
  4. Draw it to the RenderWindow
  • Problem does not happen if Texture is taken by reference !
  • Problem does not happen if Sprite is not drawn to the RenderWindow ! (Texture content seen with tex.copyToImage().saveToFile("tmp/fig" + std::to_string(i++) + ".png");)
cmake_minimum_required(VERSION 3.21.0)
include(FetchContent)

project(Demo)

### CMake config ###
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

message(STATUS "GCC detected, adding compile flags")
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g1")

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

### Dependency declaration ###

FetchContent_Declare(
  sfml
  GIT_REPOSITORY "https://github.com/SFML/SFML.git"
  GIT_TAG        2.6.1
)

### Dependency population ###

set(BUILD_SHARED_LIBS OFF)

# sfml
set(SFML_BUILD_EXAMPLES OFF)
set(SFML_BUILD_DOC OFF)

set(SFML_BUILD_NETWORK OFF)

set(SFML_BUILD_AUDIO ON)
set(SFML_BUILD_GRAPHICS ON)
set(SFML_BUILD_WINDOW ON)
# !sfml

FetchContent_MakeAvailable(sfml)

set(SRCS ${CMAKE_CURRENT_LIST_DIR}/test.cpp)

add_executable(${PROJECT_NAME} ${SRCS})

target_link_libraries(
  ${PROJECT_NAME}
  sfml-graphics
  sfml-window
  sfml-system
  sfml-audio
)

Code (1)

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow win(sf::VideoMode(640, 480), "Title");

    sf::RenderTexture rtex;
    rtex.create(50,50);

    sf::CircleShape shape(25);
    shape.setFillColor(sf::Color::Red);

    while(win.isOpen())
    {
        // render texture
        rtex.clear(sf::Color(0x00000000));
        rtex.draw(shape);
        rtex.display();

        // render window
        win.clear(sf::Color(0x1a5e21FF));

        sf::Texture tex = rtex.getTexture();
        sf::Sprite sprite(tex);
        win.draw(sprite);
        
        win.display();

        sf::Event event;
        while(win.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                win.close();
            }
        }
    }
}

Code (2)

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow win(sf::VideoMode(640, 480), "Title");

    sf::RenderTexture rtex;
    rtex.create(50,50);

    sf::CircleShape shape(25);
    shape.setFillColor(sf::Color::Red);

    while(win.isOpen())
    {
        // render texture
        rtex.clear(sf::Color(0x00000000));
        rtex.draw(shape);
        rtex.display();

        // render window
        win.clear(sf::Color(0x1a5e21FF));

        const sf::Texture & tex = rtex.getTexture(); // <-- here
        sf::Sprite sprite(tex);
        win.draw(sprite);
        
        win.display();

        sf::Event event;
        while(win.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                win.close();
            }
        }
    }
}

Code (3)

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow win(sf::VideoMode(640, 480), "Title");

    sf::RenderTexture rtex;
    rtex.create(50,50);

    sf::CircleShape shape(25);
    shape.setFillColor(sf::Color::Red);

    while(win.isOpen())
    {
        rtex.setActive(true); // <-- here

        // render texture
        rtex.clear(sf::Color(0x00000000));
        rtex.draw(shape);
        rtex.display();

        rtex.setActive(false); // <-- here

        win.setActive(true); // <-- here

        // render window
        win.clear(sf::Color(0x1a5e21FF));

        sf::Texture tex = rtex.getTexture();
        sf::Sprite sprite(tex);
        win.draw(sprite);
        
        win.display();

        win.setActive(false); // <-- here

        sf::Event event;
        while(win.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                win.close();
            }
        }
    }
}

Code (4)

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow win(sf::VideoMode(640, 480), "Title");

    sf::RenderTexture rtex;
    rtex.create(50,50);

    sf::CircleShape shape(25);
    shape.setFillColor(sf::Color::Red);

    while(win.isOpen())
    {
        rtex.setActive(true); // <-- here

        // render texture
        rtex.clear(sf::Color(0x00000000));
        rtex.draw(shape);
        rtex.display();

        //rtex.setActive(false); // <-- here

        win.setActive(true); // <-- here

        // render window
        win.clear(sf::Color(0x1a5e21FF));

        sf::Texture tex = rtex.getTexture();
        sf::Sprite sprite(tex);
        win.draw(sprite);
        
        win.display();

        //win.setActive(false); // <-- "not" here

        sf::Event event;
        while(win.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                win.close();
            }
        }
    }
}

Expected behavior

The shape is drawn on the RenderTexture and the RenderTexture is drawn on the RenderWindow

image

Actual behavior

Code (1) and (4) : the shaped is drawn without color

image

Code (2) and (3) : expected behavior

image

I cannot reproduce any of the blacked out circle screenshots you showed using the 4 source snippets provided. I tried this with SFML 2.6.1 on Windows 11 64-bit with MSVC 19.38.33134. Also tried with clang-cl 16.0.5.

Code 1:
image

Code 2:
image

Code 3:
image

Code 4:

image

Sooo, writing this whole thing made me realize I did not upgrade by graphic drivers since 6 months ago, so I upgraded them to latest and now I cant reproduce...

Did I just spend my weekend tracking down a hardware specific issue I could have solved by upgrading my drivers from the start ?

Software development is unforgiving ...

Closing this as driver bug ๐Ÿ˜‰