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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Kipernal

Pages: [1] 2
1
Window / Re: Stack overflow in GlContext::ensureContext()
« on: August 21, 2016, 06:29:24 pm »
Alright, that makes sense.  One of the comments in the source says "If there's no active context on the current thread, activate an internal one" so I just assumed SFML by default would be okay it.  Thanks for the information!

2
Window / [Resolved] Stack overflow in GlContext::ensureContext()
« on: August 21, 2016, 03:36:47 pm »
Hi all,

I'm having a problem where initializing anything that uses a GLResource causes a stack overflow when initialized on a separate thread:

#include <SFML/Graphics.hpp>

int main()
{
        sf::Window w;
        auto thread = std::thread{ []
        {
                sf::Texture t;  // Stack overflow occurs here
        }};
        thread.join();
        return 0;
}

What happens here is:
Texture::Texture() calls
GlResource::GlResource(), which calls
GlContext::ensureContext(), which calls
GlContext::getInternalContext(), which calls
Context::Context() (trying to create an internal context), which calls
GlResource::GlResource(), and now we're in an infinite loop.

I know threading is a Bad Thing™, but in order to have smooth window resizing events and drawing need to happen on separate threads, and you can only pump events from the thread that created the window.  So I need to create a window and poll its events in thread #1, and draw to it in thread #2.  Creating the window and drawing to the window both use GLResources, but I'm running into the error above.  If anyone could shed some light on this issue I'd be very grateful.

3
Graphics / Re: RenderTexture reuse
« on: June 26, 2015, 01:36:31 pm »
Went ahead and made a pull request.  Thank you for the help, everyone!

It isn't even as complicated as you think. sf::Texture already has a member called m_pixelsFlipped which is only set when it is an FBO attachment, so that can be checked for in the draw() method.

I noticed that, but unfortunately m_pixelsFlipped is also set to true in Texture::update(sf::Window, ...), which looks like it would result in the texture being rebound every call to draw if it was based on the window.

4
Graphics / Re: RenderTexture reuse
« on: June 25, 2015, 01:50:30 pm »
Can confirm that all three of those work.

Would it be worth it adding #2 into SFML?  It is technically a driver bug but this seems like the kind of thing SFML would handle to make everything "just work," and the fix seems to be incredibly easy.  I just tried adding a flag to sf::Texture that marked it as belonging to a RenderTexture and then, at the end of RenderTarget::draw, added the following code:

if (states.texture && states.texture->m_ownedByRenderTexture)
{
    Texture::bind(0);
    m_cache.lastTextureId = 0;
}

Seemed to make everything work alright.

5
Graphics / Re: RenderTexture reuse
« on: June 24, 2015, 05:21:00 pm »
Can you check which RenderTexture backend is used -- RenderTextureImplDefault or RenderTextureImplFBO?

RenderTextureImplFBO is used. If I force priv::RenderTextureImplFBO::isAvailable() to always return false, causing SFML to use RenderTextureImplDefault instead, everything works correctly, drawing a red and blue square.

Can you try if an OpenGL call glFinish() in place of/additional to RenderTexture::display() changes something?

I tried putting glFinish() before, after, and in place of both calls to renderTexture.display(), but there was no change (based on the circle test).

6
Graphics / Re: RenderTexture reuse
« on: June 24, 2015, 02:13:28 am »
@Hapax Tried a few things, but all of them still drew the same artifact-y circle:

  • Windows compatibility modes (7, XP SP3, 98/ME)
  • Removing the calls to renderTexture.display()
  • Calling renderTexture.display() twice, one immediately after another
  • Calling renderTexture.display() once before drawing the circle and once after

This code outputs both image files to be correct. (possibly due to copying them from VRAM to RAM)

I mentioned this before, but certain function calls result in the correct image being shown on-screen.  copyToImage being called on the RenderTexture's texture is one.  Calling applyTexture(NULL) on the RenderWindow (after making it public) is the other.

EDIT: spelling

7
Graphics / Re: RenderTexture reuse
« on: June 23, 2015, 10:28:46 pm »
Since it seemed to be only the people who are statically linking who are getting the wrong result, I re-tested it statically. It still worked and, in a similar direction of thought to you, Kipernal, I'm providing my built executable for you to test. Actually, I'm providing two as a check to see if it's just the render texture's clear() that's failing (or clearing with the wrong colour). The links to the executables are directly below the source code.

Just tried both executables, and I get the exact same results as Rosme on my home computer (AMD Radeon R7 200) and my laptop (Intel integrated).  That is, two red rectangles on the first test, and two red rectangles with two green circles inscribed in them, and blue artifacts around the second circle on the second test.



EDIT: wording

8
Graphics / Re: RenderTexture reuse
« on: June 23, 2015, 07:59:03 pm »
Just tested it on my laptop at work to see if there was any difference and it's working on that (showing one blue rectangle and one red rectangle) while the exact same executable shows two red rectangles on my home machine.  Environment there was Windows 7, 64-bit, with SFML static and integrated Intel graphics.

At any rate this shows that it's not just my build environment--the exact same binary is producing two different results on two different machines.

9
Graphics / Re: RenderTexture reuse
« on: June 23, 2015, 05:36:56 am »
Alright, I just tested the exact same code you posted above (the one without the QuickSprite) using SFML 2.3 Release, Visual Studio 2013, building for 32-bit and with dynamic linkage, but unfortunately I'm still getting two red squares.  Naturally if I add window.draw(sf::RectangleShape{}) between the two draw calls I get one red and one blue, as before.

Also should probably mention just in case that my graphics drivers are up to date.  Exact version is probably meaningless but just in case it's listed as 8.01.01.1443.

10
Graphics / Re: RenderTexture reuse
« on: June 23, 2015, 04:27:35 am »
Inheriting from sf::Sprite?  :o

Not something to keep around, of course, but sf::Sprite doesn't come with a constructor that takes a position and a texture and having temporaries around just cluttered the code.  Temporary insanity is why it was a class instead of a function that just returned a sf::Sprite.  :P

Your two codes have more differences that just that line. The colours theirselves are represented differently. In one code, they're variables; in the other, they're explicit SFML colours (even if one of them is "Bed"). These differences could lead on to other errors such as the variables not being set properly, or being altered by QuickSprite or something.
However, that's unlikely...

Whoops.  Those were just mistakes I made while cleaning up the code before posting it here.  I was originally doing some other color testing stuff and that's why one version has (misnamed) variables and the other just uses the sf::Color constants.  The result doesn't change though.

May I ask how you narrowed down the function in SFML that you think is causing your error?

Stepped through the debugger, skipping over certain functions to see what caused the blue rectangle to appear.  When I found what the functions were, I temporarily made all of RenderWindow's members public and called them directly (in place of the window.draw(sf::RectangleShape{}) in the above code).  With those functions in place the blue rectangle appears.

Also, it would likely be helpful (to others that know more about this) if you could provide information on which version of SFML you are using, which operating system, which IDE (if you're using one), and which compiler. Whether you're running in debug or release, and whether or not you're statically linking might be of use too.
It's odd that the code I posted works differently for you so it looks like it is: in SFML somewhere, some compiler difference, or possibly a linking error. You might want to make certain that all libraries are linked correctly and you're using the latest versions of DLLs (if you're using them) etc..

Sorry about that--since this started as a conceptual question it never crossed my mind to post that stuff.  Here's the information:

OS: Windows 8.1, 64 bit
Graphics card: AMD Radeon R7 200 Series (2048 MB memory)
SFML versions tested: Latest development snapshot
Compiler: Visual Studio 2015 RC.  Building for 32-bit.
Linkage: Static

I also tested on a super cheap laptop I have and that also gives two red squares.  Same specs as above except for the graphics card, which is probably just an integrated Intel chip.



EDIT: Since it makes sense to make a single sprite that lasts as long as the render texture and re-use it the same way that the render texture is re-used (rather than re-creating and destroying the sprite twice per frame), I re-wrote the code:

Does this still give you the wrong result?

Yep, unfortunately.   :-\

11
Graphics / Re: RenderTexture reuse
« on: June 23, 2015, 03:30:16 am »
Actually my QuickSprite was even lazier (I just directly inherited from sf::Sprite, though in retrospect I really should have just made a function that returned a normal sf::Sprite--no clue why I didn't...), but fundamentally they were the exact same thing.  I still did try copying and pasting your exact code, though, but it still shows two red rectangles on my screen.  Thanks for trying, though!  :)




That being said I did some more testing and I think I figured out what was stopping me from just reusing the RenderTexture and why it was drawing two red squares instead of two blue squares.  Sort of.  I don't want to say that it's a bug in SFML per se, but it seems really suspicious because the implication is that drawing using the same RenderTexture will actually always work...unless the two draw calls that use that RenderTexture's texture are not broken up by a call that uses a different/null texture.

Basically, this code, as mentioned before, does not work (at least on my machine):

window.clear(sf::Color::Black);

// Draw the first red rectangle
renderTexture.clear(red);
renderTexture.display();
window.draw(QuickSprite{ 0, 0, renderTexture.getTexture() });

// Draw the second blue rectangle
renderTexture.clear(blue);
renderTexture.display();
window.draw(QuickSprite{ 256, 256, renderTexture.getTexture() });

window.display();
 

This code, however, does:

window.clear(sf::Color::Black);

// Draw the first red rectangle
renderTexture.clear(sf::Color::Red);
renderTexture.display();
window.draw(QuickSprite{ 0, 0, renderTexture.getTexture() });

// Note this call--it seems to do nothing but without it we get two red squares
window.draw(sf::RectangleShape{});

// Draw the second blue rectangle
renderTexture.clear(sf::Color::Bed);
renderTexture.display();
window.draw(QuickSprite{ 256, 256, renderTexture.getTexture() });

window.display();
 

All it takes is a request to draw something with a null texture and suddenly I can reuse the RenderTexture to draw separate things like I wanted. I narrowed down the exact function calls that are necessary and it turns out it's the RenderWindow's applyTexture(NULL) call (and probably the call to activate(true) before that as well?).  I don't know enough about OpenGL to know why this happens, if it's just a fluke, or if it's actually an oversight in SFML.  Can anyone shed some light on this?

12
Graphics / Re: RenderTexture reuse
« on: June 22, 2015, 05:54:51 pm »
For a certain shader effect I need a (somewhat) high resolution rendering of the object that isn't affected by the current window's view--pulling the view out too far causes artifacts.  My basic idea was to render to a RenderTexture, then have a sprite use that texture, and then move onto the next object in line.  The main problem is that there can be a lot of these objects on the screen at once, so giving them all their own RenderTexture just isn't an option.  But that being said it also means that I don't need to actually preserve the texture's image data across frames, if that helps.

13
Graphics / RenderTexture reuse
« on: June 22, 2015, 04:33:41 am »
I'm trying to find a way to have one RenderTexture that's reused multiple times throughout one frame.  Basically something like this:

Code: [Select]
// Render stuff to a reusable RenderTexture
// Use the RenderTexture's texture in a sprite

// Clear the RenderTexture, render new stuff to it
// Use the RenderTexture's texture in a different sprite

// Clear the RenderTexture, render new stuff to it
// Use the RenderTexture's texture in a different sprite

// Clear the RenderTexture, render new stuff to it
// Use the RenderTexture's texture in a different sprite

// Clear the RenderTexture, render new stuff to it
// Use the RenderTexture's texture in a different sprite

// (etc.)

My previous attempt just used a ton of RenderTextures, one for each object that needed it, but since they're not lightweight objects like normal textures are (relatively speaking), that gets out of hand really quickly, and causes a crash after too many have been allocated and memory runs out.

After that I tried just allocating a pool of RenderTextures and doling them out to whoever needed them, but RenderTextures can't be resized without arduously destroying and recreating their context (it takes about a quarter of a second on my machine--completely impossible without the user noticing), having a ton of RenderTextures that I might never need uses a lot of memory, and having a fixed size creates an artificial limit that I don't really like hanging over my head.

Finally, I tried just copying the RenderTexture's texture to a new Texture and using that, but even using glCopyImageSubData the performance hit was still too much.

So none of these options are really all that great.  I did try one other thing, but the results were kind of weird:

sf::RenderTexture renderTexture;
renderTexture.create(256, 256);


// RenderWindow creation and event loop boilerplate here
{
        window.clear();
       
        renderTexture.clear(sf::Color::Red);
        renderTexture.display();
        window.draw(QuickSprite{ 0, 0, renderTexture.getTexture() });

        renderTexture.clear(sf::Color::Blue);
        renderTexture.display();
        window.draw(QuickSprite{ 256, 256, renderTexture.getTexture() });

        window.display();
}
 

All this code is supposed to do is draw a red rectangle (via a RenderTexture) on one part of the screen and a blue one on another.  I didn't really expect it to work...and it didn't.  But what caught my attention was that instead of drawing two blue rectangles like I thought (or one of each color like I hoped), it drew two red ones, and I can't imagine why.  I also noticed while trying to figure this out that if I add renderTexture.getTexture().copyToImage() before the call to window.draw it works as I wanted, drawing a red and blue rectangle.  Specifically glGetTexImage does some magic to get it working, but that's a hack and I'm like 99% sure that even if it wasn't a performance hit I couldn't actually rely on it to do this completely unrelated task.


Anyway, this is just a very long-winded way of asking if there's any way I can get the reuse of RenderTextures working, because nothing I've come up with so far has really been satisfactory.  I'd be super appreciative if anyone out there has any ideas and could share them with me.

14
Feature requests / Re: Clipping mask implementation proposal
« on: May 03, 2015, 01:41:42 am »
Alright, so I should probably get this out of the way first: I didn't do this with any sort of intention of "fighting" with your implementation--when I said "battle it out" I didn't think you'd take it so literally.  I meant let the people decide which API they like better, and that's really the whole thing.  This is just about APIs, and in fact I couldn't care less whose makes it in.  If someone else pops up tomorrow with a third design that everyone accepts immediately I'd be just as happy.

This, then, is why I didn't instead submit it as a comment on your pull request--the fundamental design was so different that it'd basically just be saying "change the very foundations of your API" which wouldn't have accomplished anything.  I figured that by designing my own API separate from yours we could have the community decide which they liked better, and then focus on the implementation details.  Implementing clipping masks isn't hard, as evidenced by the fact that someone like me with very little OpenGL knowledge could put something together.  So the fact that it's taken so long for anything to come up suggests that the difficulty of the creation of this feature comes more from how to build an easy-to-understand API rather than the nitty-gritty OpenGL calls.

That is why I did this and why I said "competition's always good".  I made this because I thought up an API for clipping masks that I liked while experimenting with the OpenGL stencil buffer, and thought maybe the SFML community might have some opinion on it.  And that's it.

What about when people just need simple clipping for GUIs? You offer no way to utilize glScissors for simple rectangle clipping.

As I mentioned before that's one thing that your implementation provides that mine doesn't, pretty much exclusively because I was just focusing on how to get stencil tests under control.

What if someone wants to clear the mask and apply a different one? There doesn't appear to be any way to do that with your design.
There is, under the currently-named RenderTarget::clearStencilBuffer function.  There's also an alternative I mention below.

In the case of blend modes there isn't any better option but to expose the entire enums simply because there is no better way to wrap it. But when it comes to stencils I don't think we need to expose the entire interface. I mean, what exactly is the point of even giving away that the clipping API uses the stencil buffer? Isn't this kind like of exposing that the graphics module uses libjpeg?

This is not wrong, and was something I struggled with.  If I'm being honest I'm not sure I'm 100% happy with the idea that StencilSettings serves the double duty of both creating and applying masks, but I felt that with the enums 90% of users wouldn't need to care from an API standpoint, and the other 10% would be able to take advantage of it in order to do advanced stencil operations if they desired.  Again, like with BlendMode.

If we wanted to give access to the stencil buffer then we should, or we should implement clipping masks (as my design does). Just to say, what if we want to port SFML to another backend or platform that doesn't support the stencil buffer or there is a better way to implement clipping? But you can't now because you shackled one foot and one leg to the stencil buffer.

Again, more than valid.  I chose the route of giving the user more flexibility if they really needed it and then hiding that power from users that don't, but of course this means the ability to use clipping masks is more tied to OpenGL stencil buffers specifically than might be otherwise.

Doesn't this totally defeat the purpose of what one of the biggest reasons is for implementing clipping masks? What if you want to limit your GUI to an area of the window but that GUI will not explicitly use the clipping mask?

If you wanted to limit a GUI to an area of the window then you'd draw a mask onto the window, then draw the GUI with StencilTrace, ensuring that the RenderStates are properly propagated to the GUI's children elements.

So just say a sub-drawable decides it wants its own mask - so it clears the stencil buffer (actually it needs the glClear function because this design doesn't expose that). Then it draws what it wants and returns from its draw function. Now the caller may not even know that the mask was changed (or that it may need to entirely redraw the mask, but what if it changed the mask itself?).

If a sub-drawable wants its own clipping mask, it can increment the stencilReference member variable of the StencilSettings object it got in its draw call.  This causes it to write different values to the stencil buffer than its parent, which can then be traced over without affecting the parent's "portion" of the screen.  This is somewhat complicated, however--I will fully admit that.

https://github.com/SFML/SFML/compare/master...Kipernal:master#diff-ee21bf2821ee1b97f677cabb9bb964c5R33
This isn't how you are supposed to add gl functions.

Of course not. But as I mentioned in the comment above that line, it's not in GLLoader.hpp and I didn't want to mess with that file.  I figured I'd let whoever was in charge of knowing exactly how to handle it take care of that one single function.

15
Feature requests / Re: Clipping mask implementation proposal
« on: May 02, 2015, 04:16:42 pm »
Without looking at the implementation, I didn't notice that you had a structure similar to BlendMode, to have full control over stencil buffer operations. Maybe we could do the same as for blending modes: start with the most common modes (as a simple enum), and make it evolve to a structure that exposes all the underlying OpenGL stuff later, only if it is really needed.

I'm not 100% sure what you mean--if you're talking about providing "simple" objects that don't require users to dig deep into the documentation that's what (the currently named) StencilCreate, StencilTrace, etc. are for.  They serve the same purpose as, for example, BlendAlpha and BlendMultipy.

A spontaneous thought: since these clipping mask are essentially set operations, maybe some terms could be taken from there? E.g. "union" instead of "add".

I like the idea of using "union" somewhere in there as it makes a lot of sense, but just calling something "MaskUnion" (not that you were implying that be the full name) doesn't make it clear which broad operation you're performing (adding to the mask versus tracing the mask).  We need another word in there, and it's finding that word that's been causing me trouble.  Personally I'm leaning towards the "MaskCompose" I suggested last time, as it doesn't necessarily imply creating a new mask (like the current "StencilCreate"), and it doesn't imply that the user needs to have an already-existing mask (like "MaskAdd" or "MaskAddTo").

But it only makes sense if the relation to sets is relevant for the user. Is it possible to support other operations, such as the intersection between two masks, yielding a third mask? I'm referring to the combination of masks themselves, not rendering an object using a mask.

I haven't actually tried it, but as far as I know you sort of can.  OpenGL stencil operations are arithmetic, not bitwise, so you can add or subtract 1 from the current pixel's stencil value but not set or clear a specific bit.  Basically you can count how many times there's been an overlap in drawing masks but not specifically pinpoint which masks caused it, if that makes sense.  That being said if you're only using the default objects, which only write 1s to the buffer, then this doesn't matter much. :P

Pages: [1] 2