Max Texture Units
Never callglGetIntegerv(GL_MAX_TEXTURE_UNITS, &MaxTextureUnits);
because this is for the fixed pipeline which is deprecated now. It would return a low value such as 4.
For GL 2.0 and onwards, use the followingglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &MaxTextureImageUnits);
The above would return a value such as 16 or 32 or above. That is the number of image samplers that your GPU supports in the fragment shader.
The following is for the vertex shader (available since GL 2.0). This might return 0 for certain GPUs.glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &MaxVertexTextureImageUnits);
The following is for the geometry shader (available since GL 3.2)glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &MaxGSGeometryTextureImageUnits);
The following is VS + GS + FS (available since GL 2.0)glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &MaxCombinedTextureImageUnits);
and the following is the number of texture coordinates available which usually is 8glGetIntegerv(GL_MAX_TEXTURE_COORDS, &MaxTextureCoords);
The problem is that SFML only queries a single limit since it has no knowledge of how you distribute them between the stages
I think for most intents and purposes, checking against the combined limit should be enough.
Unfortunately, I simply can't trust the current SFML code to tell me how many texture units is safe to use.This is correct, because SFML doesn't provide you with this information, so there is nothing to trust anyway. ;)
I think you should do a bit more reading about how samplers and texture image units interact with each other.
Also, I'm not sure what you would do even if you did know the limits of each individual stage.
I'm not sure what samplers have to do with my post at all. I just want to know how many textures I can use in my fragment programs.Samplers source their data from texture image units. There are 2 bindings on the way from the texture object itself to the sampler inside a shader stage. The first one is the combined texture image unit binding, you can't bind more textures at a time in total than that amount. The second binding is from texture image unit into shader sampler. OpenGL probably does the mapping automatically for us, but there is a mapping somewhere. All that matters for that second one is that the number of active mappings doesn't exceed the maximum for the corresponding stage.
Other graphics middleware I've worked with do provide an interface to query the max number of texture units for a fragment program. So I guess I was looking at the SFML code through that lens.They also expose each shader individually and let you do things with them. The only point where SFML asks you about a stage is when you have to provide the source for the specific stage. Everything that happens after that happens at a program level. It doesn't matter whether your sf::Shader only has a vertex shader stage or only a fragment shader stage, SFML will treat it the same regardless.
exit with a "hardware not supported" error on startupThis doesn't seem very user-friendly and should really only happen as a very last resort to avoid undefined behaviour.
or better yet, have a simpler fallback shaderThe question now then is: If this is possible, why not work bottom up and make sure that the shader stays simple enough to function on all hardware that is potentially supported? The limits these days are getting so large, to the point where I have to ask myself: Are people actually going to make use of this in a real-world scenario?
Samplers source their data from texture image units.
... (cut) ...
Needing to know how many textures you can use in a specific shader stage is the same as asking how many active sampler bindings can exist for that shader stage.
They also expose each shader individually and let you do things with them. The only point where SFML asks you about a stage is when you have to provide the source for the specific stage. Everything that happens after that happens at a program level. It doesn't matter whether your sf::Shader only has a vertex shader stage or only a fragment shader stage, SFML will treat it the same regardless.
This doesn't seem very user-friendly and should really only happen as a very last resort to avoid undefined behaviour.
The question now then is: If this is possible, why not work bottom up and make sure that the shader stays simple enough to function on all hardware that is potentially supported? The limits these days are getting so large, to the point where I have to ask myself: Are people actually going to make use of this in a real-world scenario?
See, the thing about textures is that well... they're textures. The only difference between them and generic buffer objects are the samplers and texture operations that can be performed on them. In fact, OpenGL really doesn't care at all about how you end up using the data, which is why texture buffer objects exist as well. Just because you can make use of 32 samplers in a certain stage, does that mean that there really is no better alternative? I'm pretty sure there always is. The thing with textures is that they are just too easy to use and get away with. Rather than thinking of more clever ways of getting data into the shader, people just push the number of textures they end up using and obviously the GPU vendors follow suit and tailor the hardware/API to the usage patterns of the end users, the typical positive-feedback loop.
Just think about it, even in those big AAA games that are known to push GPUs to their limits, when you look at an object somewhere (normally a shader is used per material, so it is probably rebound whenever new object types are rendered) are you able to recognize all those... what... 8, 16, 32 textures that were potentially used to render it? I think textures are simply abused to do "other things", and given that OpenGL provides so many other (potentially better) ways to get the job done, there is no excuse to have to do things like this if you ask me.
Even a "simple" program should verify it's ability to function properly, unless it's purely a hobby or learning pursuit.That's what the OpenGL specification is for. Conforming implementations guarantee a minimum working set of capabilities on which software can rely on. I don't know what you are thinking, but none of those values you are querying is allowed to return 0, at least since 3.0 according to the official reference page for glGet() (https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml). In fact, the minimum allowed values are fairly generous for all but the most demanding applications if you ask me. Worrying that a program will fail to function properly because there might not be enough resources to use is not an OpenGL thing. It might be the case for other APIs like DirectX, but when you know that industrial and other more "serious" applications rely on your specification, you leave less room for vendors to interpret your requirements.
It could simply be struct like ContextSettings that gets filled in with stuffHaving a central location for such a broad range of unrelated attributes isn't good style if you ask me. Any time a feature is added/changed that relies on such values, changes will have to be made to multiple modules instead of solely at the site at which the value is relevant. This increases coupling, and makes proper maintenance of the code slightly more tedious with every iteration. The sfml-window module's sole purpose is to provide a working GL environment on which other modules or your own code can build on top of. It shouldn't try to take over responsibility when it doesn't have to. Sure, you and other coders might want it to, because we end up saving you work, but keeping the implementation clean and easily maintainable has higher priority, especially given SFML's limited development resources.
max texture sizesf::Texture::getMaximumSize()
GL_MAX_TEXTURE_UNITSToo specific, can perform on your own with current master.
geometry shader support check (should that be added to SFML)#428 (https://github.com/SFML/SFML/issues/428)
a mipmap support check#123 (https://github.com/SFML/SFML/issues/123)
shader profiles supportedCan be derived from context version.
This would be "simple" in that the casual user could totally ignore this HardwareCapabilities struct. On the flip-side, for any more serious software release, the programmer could query it and make it's own decisions how to handle this info, and validate or alter the program's functionality (e.g. simpler shaders). And this could be done without touching any opengl, remaining true to the spirit of SFML's "simple" API.There are 2 kinds of "Simple", and over time I feel SFML is diverging from one to the other (which is not necessarily a bad thing).
By not having it, it's no more simple for a casual user, but much less simple for any programmer who is writing a serious software release.If you replace "any programmer who is writing a serious software release" with "programmer who is used to how 90% of all other libraries function" you might be on to something. ;) Seriously though, the only reason I can think of for why people ask open source libraries to implement application specific feature XYZ is because a) it would be free of charge to them and b) it would save them manhours which they could spend on something else instead. If libraries charged their users for implementing very specific features, they would probably think twice about whether they should implement it themselves instead. We develop with the community in mind, and not single users.
You're basically "forcing" all those users to write this low level code themselves. That's the opposite of simple.Do you really expect any arbitrarily selected application requirements to be reducible to an implementation that you will always deem "simple? It's a simple fact of life, not only in software development. The more complex the task at hand, the more effort it will take to fulfil said task. Building an airport will take considerably more work than building a house, even if the contractor has a lot of experience building runways and terminal buildings.
Because it's like SFML does 95% of the base functionality that every fully robust app will need, but leaves that 5% where the user must delve into the very low level opengl code that SFML otherwise successfully abstracts away.Same argument as above. If SFML really went out of its way to make sure 100% was covered in every scenario, you might have forgotten that those 5%s add up over time to something that is truly monstrous.
To me, the "S" in SFML is largely about allowing me to avoid low level opengl.Avoiding is not the same as ignoring. I consider the former optional, while the latter is what some people hope to get away with, but end up burning themselves with. If you know what you are doing is beyond the capabilities of what most SFML users might make use of, always be prepared to write OpenGL code.
But SFML also allows for layers of depth. A casual user can create a few sprites and move them around. A more advanced user can employ VertexArrays, Shaders, RenderTextures, etc. The casual user can ignore those. You guys make the use of these more advanced concepts (shaders, render textures, etc) MUCH more pleasant to work with ("simple") than writing the raw opengl. So again, I think you have been largely successfully here. Except, perhaps, a few little edge cases like this.You consider this an edge case, I consider this as the next layer of depth in your words. Just because OpenGL symbols aren't in the sf:: namespace, doesn't mean that it is not considered as the next logical step after usage of sf::Shaders and sf::RenderTextures. We could just pull everything into an sf::ogl:: namespace, but since it would serve no practical purpose, we just recommend anybody who is interested to learn more about OpenGL and how they can use it alongside SFML.
In fact, the minimum allowed values are fairly generous for all but the most demanding applications if you ask me. Worrying that a program will fail to function properly because there might not be enough resources to use is not an OpenGL thing.
Having a central location for such a broad range of unrelated attributes isn't good style if you ask me.
There are 2 kinds of "Simple"...
I don't know about you, but I find many programmers these days unreasonably assuming that they should only have to use a single library and that library has to do everything they need it to do in their specific project.
Seriously though, the only reason I can think of for why people ask open source libraries to implement application specific feature XYZ is because a) it would be free of charge to them and b) it would save them manhours which they could spend on something else instead. If libraries charged their users for implementing very specific features, they would probably think twice about whether they should implement it themselves instead. We develop with the community in mind, and not single users.
Maybe an SFML user is working on your new android port. GLES2 defines a minimum texture size of 64x64. So by your logic, nobody should use any textures larger than 64x64 on android? That's absurd, and likely why SFML has implemented a resource check on the max texture size. I fail to understand what's so different about texture units.I was referring exclusively to the texture image unit minimums, not the texture size minimum. The difference between the maximum texture size and the number of texture image units is that the former has been around for much longer, and is something SFML guarantees to provide, even on an OpenGL 1.1 context. The whole question of texture image units doesn't make much sense unless shaders are supported, which is not always the case and which is why you can check for optional shader support.
SFML's default OpenGL version on windows is 2.0, which only has a minimum number of 2 texture units for fragment programs. Obviously most machines you encounter will have more than that. But again, relying on the minimum isn't useful here.I never said you should limit yourself to a specific OpenGL version, and trying to do so would often not get you anywhere anyway, as the implementation is allowed to create any newer version that is fully compatible with whatever you requested. The minimum limits are defined by version, and often for good reasons. If a system was only able to support up to 2.0 for whatever reason, then pushing your shaders to the maximum might not even be such a great idea in some cases.
Sure, I could just enforce a higher OpenGL version. But why would I want to artificially limit my game to run on OpenGL 3+ when I can get it to run on 2.x with a few graphics adjustments? There's lots of old hardware out there. Those cards may even be powerful enough to run at full graphics settings.
I'm a little disappointed in how you've interpreted this discussion. I'm not here to get free labor out of you. Although I do appreciate your expertise and willingness to talk here on the forum.I know you've already implemented this yourself and are not asking for free labour, I was referring to feature requests in general, sometimes for seemingly trivial things that are obviously way beyond the scope of SFML. The best way for something to be implemented in SFML is a working implementation to accompany the feature request. Since people often fail at that already, I just have to assume that they didn't give the possible implementation enough thought, and decided to request a feature that they happened to need for the project they are currently working on. It's happened many times before, just browse through the feature request forums. ;)
Honestly, I already implemented what I needed in a fraction of the time we've both put into this thread.
I just wanted to propose what I thought might be a fairly simple change that would make SFML more useful to many users, not just me.This is something that many people who have proposed features in the past seem to assume. I don't know about you, but I've seen a fair share of SFML applications and other use cases, and none of them rely on knowing the texture image unit limit in order to function. What I always recommend people to do, in case they think we have misjudged the usefulness of their suggestion, is to find people/projects that show that it is a direly needed feature. Nothing speaks more words than a bunch of links to the code of SFML projects that all contain the same OpenGL code that is lacking in SFML. Often times, suggestions already fail to gain any momentum at this step, and unfortunately I think your suggestion would to. ;)
Shaders are not application specific. They're a core part of SFML's API.While they are part of the SFML API, I wouldn't say that they are part of the core API. A developer that has to support hardware that may very well be ancient can't rely on shaders being universally supported. Instead of enabling functionality that is only possible in the presence of shaders, they choose to just ignore them. sfml-graphics is completely usable without shader support. In fact, SFML's sf::RenderTexture implementation has support on all hardware due to the implemented fallback implementation, so sf::Shader is really the only thing that you can't rely on being available, and thus far from being considered core in any way.
You may have insinuated I'm not a "real programmer" because I made this feature request.Not at all. If you belonged to that specific class of "programmer" I was referring to, you would still be pushing for this feature without having even a clue of what to do in case it didn't get implemented. ;) I knew from the start you already had something that worked for you, so I was just expressing my personal opinion about those that are obviously not nearly as capable as yourself. Those people can at times turn out to be very demanding when it comes to their expectations of what is to be implemented, even going so far as threatening to run away to another library altogether, like that is going to convince us. ::)
A legitimate disadvantage OpenGL has had since the beginning in comparison to DirectX is the lack of a way to check if a feature is truly implemented in hardware or is a mix of hardware/software or even fully implemented in software.
instead they sort them into hardware classes for which they had done extensive testing during development. If you plan on supporting a wide range of graphics hardware generations, this is really the only sane thing to do.
Nothing speaks more words than a bunch of links to the code of SFML projects that all contain the same OpenGL code that is lacking in SFML. Often times, suggestions already fail to gain any momentum at this step, and unfortunately I think your suggestion would to. ;)
Windows was actually pretty smooth. But for the SFML game I'm working on now, we'll have to see how much of a "second class citizen" OpenGL is on windows. Honestly, I'm not quite sure what to expect, and consider it one of the risks of this project.It's funny really, even after all this time and numerous other (http://en.wikipedia.org/wiki/United_States_v._Microsoft_Corp.) court cases (http://en.wikipedia.org/wiki/Microsoft_Corp_v_Commission), one would expect them to wise up and provide a fair playing ground for OpenGL as well. Packaging a default DirectX driver and a barely usable OpenGL driver is just as bad as packaging Internet Explorer without any alternatives with a default installation of Windows. I wonder how long and if it ever happen that they will end up in court again because of this. The problem with this kind of a lawsuit is that it isn't easily understandable by "your average consumer". They don't know the difference between DirectX and OpenGL, and they are the ones that the plaintiffs have in mind when going to court. Put simply, nobody bothered to make enough noise for this to become a real issue, and the ones who could have already been in Microsoft's boat for a long time.
However, it may be a case of "build it, and they will come". Most of the SFML projects I see are hobby projects with pretty basic graphics. Not that there's anything wrong with that. And maybe this is the user base you prefer to cater to.That's the thing, since SFML is licensed under zlib, there is no obligation to even mention it in your final software. People around here have been working hard to track down projects that do indeed make use of SFML, and all I can say is that there doesn't seem to be a lack of them.
If I had to guess, I'd say that many developers are scared off by the OpenGL-only back end. That may be a combination of legit thinking (e.g. "I can't port to XBox"), and superstition (e.g. "you can't use OpenGL on windows").Remember what I said about "real programmers"? Yeah... ;)
Packaging a default DirectX driver and a barely usable OpenGL driver is just as bad as packaging Internet Explorer without any alternatives with a default installation of Windows.
Without drivers, you will default to a software version of OpenGL 1.1 (on Win98, ME, and 2000), a Direct3D wrapper that supports OpenGL 1.1 (WinXP), or a Direct3D wrapper that supports OpenGL 1.1 (Windows Vista and Windows 7). None of these options are particularly fast, so installing drivers is always a good idea.
I really wonder how Vulkan support on Windows will turn out to look like. It is a direct competitor to DirectX 12, so there is already an obvious motivation to hinder its proliferation from the get-go.
That's the thing, since SFML is licensed under zlib, there is no obligation to even mention it in your final software. People around here have been working hard to track down projects that do indeed make use of SFML, and all I can say is that there doesn't seem to be a lack of them.
And about "build it, and they will come": SFML is not a for-profit organization. I don't see any need to lure new developers into using it, for whatever reason one could think of.
Also, about the console support: I think indie developers who come to SFML asking if it supports consoles underestimate the amount of effort/money it takes to support them, both on SFML's side and the developer's side.
In your experience, what has been the general approach of OpenGL-based software on windows? Simply some kind of instructions to update your drivers, perhaps on the website? And probably a crap-ton of support cases of people who ignored those instructions and are experiencing terrible performance? Or is there some better way of handling it?glGetString() with GL_VENDOR and GL_RENDERER will return strings like "Microsoft Corporation" and "GDI Generic" respectively. If you see any of those, chances are the user didn't bother to install proper drivers themselves or their OEM lied to them and/or simply don't care when they provided their driver package for download. The latter case is easier to answer: Never buy hardware from them again. :P The former case is a bit trickier. The first half of the problem is informing the user that there might be something wrong, the second half is getting them to acknowledge there is something wrong and take corrective measures. If they do choose to perform corrective action, I can imagine opting to open a browser pointing to either the AMD or Nvidia driver download pages to save them the hassle of searching themselves.
\glGetString() with GL_VENDOR and GL_RENDERER will return strings like "Microsoft Corporation" and "GDI Generic" respectively. If you see any of those, chances are the user didn't bother to install proper drivers themselves or their OEM lied to them and/or simply don't care when they provided their driver package for download. The latter case is easier to answer: Never buy hardware from them again. :P The former case is a bit trickier. The first half of the problem is informing the user that there might be something wrong, the second half is getting them to acknowledge there is something wrong and take corrective measures. If they do choose to perform corrective action, I can imagine opting to open a browser pointing to either the AMD or Nvidia driver download pages to save them the hassle of searching themselves.