Hey there,
I seem to be having a bit of trouble when creating RenderTextures (and occasionally normal Textures too). I basically have four problems (that are hopefully all connected):
- The create call crashes after creating around 300 RenderTextures or so (but occasionally as low as 18, and sometimes just hanging forever on call #9) regardless of the size. Destroying the RenderTexture allows me to create more RenderTextures, so it's a limit of 300 or so at any given time, not 300 total.
- If a separate thread calls create on a RenderTexture or normal Texture that was defined on the main thread, then destroying the RenderTexture or Texture will not allow me to create more than the ~300 max I mentioned above. 300 becomes a maximum for RenderTextures or Textures created like this.
- The create call is measurably slow for RenderTextures, such that I can see the program freeze briefly upon creation and in the most extreme case of calling create once every frame my FPS drops from 60 to 20.
- The memory usage for RendureTextures is bizarrely high. Creating 283 1x1 RenderTextures uses almost 2 GB of memory.
Here is a minimal example for the first point:
#include <SFML/Graphics.hpp>
#include <iostreams>
int main(int argc, char* argv[])
{
for (int i = 0; i < 400; i++)
{
(new sf::RenderTexture)->create(1, 1);
std::cout << "Created texture #" << i + 1 << std::endl;
}
}
On my system this I get the error "
Unhandled exception at 0x0364DC72 (atioglxx.dll) in out.exe: 0xC0000005: Access violation writing location 0x00000000." trying to create texture #287.
In this case, if you were to replace the RenderTextures with normal Textures there would be no problem.
If you were to delete the RenderTexture allocated in the for loop or put it on the stack so it is destroyed automatically there would be no problem.
If you were to not call create there would be no problem.
The second point is strangely specific (I mean, y'know, threads. Of course things get weird). This was the minimal example I came up with:
#include <SFML/Graphics.hpp>
#include <iostreams>
#include <thread>
int main(int argc, char* argv[])
{
sf::RenderTexture renderTextures; // For some reason we need at least one RenderTexture like this for the crash to occur.
// It doesn't even need to be created, it just needs to exist.
for (int i = 0; i < 400; i++)
{
// Define the texture in one thread, but create it in another.
sf::RenderTexture tex;
std::thread thread([&]
{
tex.create(1, 1);
});
thread.join();
std::cout << "Created texture #" << i + 1 << std::endl;
// Note that the RenderTextures are destroyed here, but we still crash.
}
}
On the latest development snapshot of SFML compiling with Visual Studio 2015 CTP6 I get "
Unhandled exception at 0x0401A610 (atioglxx.dll) in out.exe: 0xC0000005: Access violation writing location 0x00000000." trying to create texture #278.
On SFML 2.2 compiling with Visual Studio 2013 I get "
Unhandled exception at 0x68956F8A (atigktxx.dll) in out.exe: 0xC0000005: Access violation reading location 0xFEEEFEEE." trying to create texture #159.
Here, if you replace the RenderTextures with Textures the problem persists.
If you remove the first RenderTexture (the one outside of the for loop) there is no problem.
If the RenderTextures are defined and created in the same thread, there is no problem.
So all of that in summary:
- If I am using RenderTextures in one thread, I can only have ~300 created at one time before I need to destroy some. These are created very slowly and have a huge memory footprint.
- If I am using Textures in one thread, I can have as many as I want, all created instantly, with no penalty.
- If I am using RenderTextures defined in one thread and created in another thread, I can only have ~300 created in total, with the same slow creation time and memory usage.
- If I am using Textures defined in one thread and created in another thread, the same problems occur (300 total, slow, lots of memory used)
My system is set up like the following:
OS: Windows 8.1, 64 bit
Graphics card: AMD Radeon R7 200 Series (2048 MB memory)
SFML versions tested: 2.2 and latest development snapshot as of April 23, 2015 (e0d27358fb9d62fcba96e1d14fa3185ce63668e9)
Compiler: Visual Studio 2013 for SFML 2.2, Visual Studio 2015 CTP6 for the latest GitHub version. Building for 32-bit.
Linkage: Static
Also made sure I'm using the latest drivers. I updated them specifically for this test--before that the results were the same except the performance for creating RenderTextures was significantly worse and I could actually create a few
more RenderTextures before crashing. That being said at one point while running these tests my driver itself actually crashed, but I'm not sure if that's 100% relevant.
Full stack trace is here. For reference, the function being called at
WglContext::createContext is
wglCreateContextAttribsARB. This is the final call I can see in the debugger.
atioglxx.dll!0431dc72() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for atioglxx.dll]
atioglxx.dll!043f85eb() Unknown
atioglxx.dll!043ccf9e() Unknown
atioglxx.dll!043c3ae2() Unknown
atioglxx.dll!043cd2ed() Unknown
atioglxx.dll!043c3b51() Unknown
atioglxx.dll!043fd613() Unknown
atioglxx.dll!043cef6e() Unknown
atioglxx.dll!0384be01() Unknown
atioglxx.dll!04265e43() Unknown
atioglxx.dll!04264cf9() Unknown
atioglxx.dll!0426a47b() Unknown
atioglxx.dll!03747c80() Unknown
opengl32.dll!_CreateAnyContext@4() Unknown
opengl32.dll!_wglCreateLayerContext@8() Unknown
atioglxx.dll!0375a526() Unknown
> out.exe!sf::priv::WglContext::createContext(sf::priv::WglContext * shared, unsigned int bitsPerPixel, const sf::ContextSettings & settings) Line 420 C++
out.exe!sf::priv::WglContext::WglContext(sf::priv::WglContext * shared) Line 88 C++
out.exe!sf::priv::GlContext::create() Line 217 C++
out.exe!sf::Context::Context() Line 37 C++
out.exe!sf::priv::RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) Line 87 C++
out.exe!sf::RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer) Line 78 C++
out.exe!main(int argc, char * * argv) Line 286 C++
out.exe!invoke_main() Line 73 C++
out.exe!__scrt_common_main_seh() Line 261 C++
out.exe!__scrt_common_main() Line 304 C++
out.exe!mainCRTStartup() Line 17 C++
kernel32.dll!@BaseThreadInitThunk@12() Unknown
ntdll.dll!__RtlUserThreadStart() Unknown
ntdll.dll!__RtlUserThreadStart@8() Unknown
Occasionally I'll get a different stack trace, but this is more rare (note that this is for the threaded version of the problem, though I don't think it is unique to it):
atioglxx.dll!039edc72() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for atioglxx.dll]
atioglxx.dll!03ac85eb() Unknown
atioglxx.dll!03a9cf9e() Unknown
atioglxx.dll!03a93ae2() Unknown
atioglxx.dll!03a9d2ed() Unknown
atioglxx.dll!03a93b51() Unknown
atioglxx.dll!03acd613() Unknown
atioglxx.dll!03a9ef6e() Unknown
atioglxx.dll!02f1bbb6() Unknown
atioglxx.dll!03933aa2() Unknown
atioglxx.dll!03933a0b() Unknown
atioglxx.dll!039539d0() Unknown
atioglxx.dll!03935222() Unknown
atioglxx.dll!03938df9() Unknown
atioglxx.dll!02e186df() Unknown
opengl32.dll!_MakeAnyCurrent@16() Unknown
opengl32.dll!_wglMakeCurrent@8() Unknown
> out.exe!sf::priv::WglContext::makeCurrent() Line 181 C++
out.exe!sf::priv::GlContext::setActive(bool active) Line 301 C++
out.exe!sf::priv::GlContext::initialize() Line 374 C++
out.exe!sf::priv::GlContext::create() Line 220 C++
out.exe!`anonymous namespace'::getInternalContext() Line 155 C++
out.exe!sf::priv::GlContext::ensureContext() Line 207 C++
out.exe!sf::GlResource::ensureGlContext() Line 83 C++
out.exe!sf::Texture::getValidSize(unsigned int size) Line 610 C++
out.exe!sf::Texture::create(unsigned int width, unsigned int height) Line 126 C++
out.exe!sf::RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer) Line 55 C++
out.exe!main::__l4::<lambda>() Line 292 C++
out.exe!std::_Invoker_functor::_Call<void <lambda>(void) &>(main::__l4::void <lambda>(void) & _Obj) Line 1408 C++
out.exe!std::invoke<void <lambda>(void) &>(main::__l4::void <lambda>(void) & _Obj) Line 1477 C++
out.exe!std::_Invoke_ret<void <lambda>(void) &>(std::_Forced<std::_Unforced> __formal, main::__l4::void <lambda>(void) & <_Vals_0>) Line 1508 C++
out.exe!std::_Call_binder<std::_Unforced,void <lambda>(void),std::tuple<>,std::tuple<> >(std::_Forced<std::_Unforced> _Fr, std::integer_sequence<unsigned int> __formal, main::__l4::void <lambda>(void) & _Obj, std::tuple<> & _Tpl, std::tuple<> && _Ut) Line 789 C++
out.exe!std::_Binder<std::_Unforced,void <lambda>(void) >::operator()<>() Line 847 C++
out.exe!std::_LaunchPad<std::_Binder<std::_Unforced,void <lambda>(void) > >::_Run(std::_LaunchPad<std::_Binder<std::_Unforced,void <lambda>(void) > > * _Ln) Line 234 C++
out.exe!std::_LaunchPad<std::_Binder<std::_Unforced,void <lambda>(void) > >::_Go() Line 225 C++
out.exe!std::_Pad::_Call_func(void * _Data) Line 202 C++
out.exe!invoke_thread_procedure(unsigned int (void *) * const procedure, void * const context) Line 92 C++
out.exe!thread_start<unsigned int (__stdcall*)(void *)>(void * const parameter) Line 115 C++
kernel32.dll!@BaseThreadInitThunk@12() Unknown
ntdll.dll!__RtlUserThreadStart() Unknown
ntdll.dll!__RtlUserThreadStart@8() Unknown
Thanks in advance for any help you guys can give me! I really know nothing about OpenGL so this was about all I could dig up without any sort of further guidance. If anyone needs more information from me please just let me know.