Goombert
|
|
Posted on: July 16, 2014, 12:15:26 am |
|
|
Location: Cappuccino, CA Joined: Jan 2013
Posts: 2993
|
Please read the earlier topic for more discussion. http://enigma-dev.org/forums/index.php?topic=2091.0After some more digging, I found most of my initial assumptions are correct. Allow me to quote some various sources. http://www.virtualdub.org/blog/pivot/entry.php?id=180On the flip side, one of the more annoying aspects of OpenGL I've found is the tying of sampler parameters — filtering, addressing, mip map LOD bias, etc. — to textures. For a software renderer that modifies texture data for these changes, this makes sense, but it doesn't make sense for modern hardware where these are usually sampler states. It can also make sense if you consider them intrinsic to the texture, but that then breaks down if you want to do something beyond what the hardware can support. A high quality image processor really needs to support higher quality filtering than bilinear; bilinear filtering gives a really crappy gradient map. To do this, you have to emulate the higher-order filtering using lower-order filtering, and you run into the problem that if you ever need the same texture bound with different parameters in the same pass, you're screwed, because you only have one set of parameters on the texture. I do this when rendering bicubic in VirtualDub's D3D9 driver, and I can't port it to OpenGL because it's impossible to do so. I looked at the source for various OpenGL binding layers, and they all seem to emulate sampler states by pushing them into texture parameters. This sucks. http://forum.unity3d.com/threads/setting-sampler-state.21442/If you want to use the same texture with different filtering modes, and can't have some script executed in between, then yes, it does get tricky.
There's no separate sampler state in OpenGL (filtering and other modes are set onto a texture), so exposing it in D3D style is not easy. The gentlemen in that post gave slightly misleading advice, OpenGL does in fact allow you to create sampler objects, but they are an extension and not officially core until 3.3 http://docs.unity3d.com/Manual/ComputeShaders.htmlTexture samplers in compute shaders
Textures and samplers aren’t separate objects in Unity, so in order to use them in compute shader you have to follow some Unity specific rules:
Either use same as texture name, with “sampler” in front (e.g. Texture2D MyTex; SamplerState samplerMyTex). In this case, sampler will be initialized to that texture’s filter/wrap/aniso settings. Or use one of “predefined” samplers; name has to have “Linear” or “Point” (for filter mode) and “Clamp” or “Repeat” (for wrap mode). For example, "SamplerState MyLinearClampSampler" - this will have linear filter and clamp wrap mode.
This goes back to my main premise, OpenGL did not properly abstract texture resources for being the low-level graphics API it claims to be. Now I am mostly in favor of going with a mix that allows you to create sampler objects in your own custom shaders and by default having texture information per-texture, but this is compatibility breaking. This means you would have to code each texture you want repetition for and each one you want to set the filtering of, unless you use a custom shader. The choice is ultimately up to everyone else, as I really can't make up my mind on the issue, but I would like to see a sample of everyone's opinions.
|
|
|
Logged
|
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.
|
|
|
|
Goombert
|
|
Reply #2 Posted on: July 16, 2014, 01:35:13 am |
|
|
Location: Cappuccino, CA Joined: Jan 2013
Posts: 2993
|
Ok, I will detail them for you. Those in favor of per-texture like OpenGL -----------------------------------------------------------Pros * More control over textures. * Less interference with the GPU, most textures can be configured at startup and then left alone. Cons * More coding, you can't just turn on interpolation and leave it, if you want it on all for all textures you have to loop them. * May slow down Direct3D9 since we'd have to interfere with the GPu every time you bind a texture in order to pass its sampler state to the shader or FFP. * Much harder to perform batching, we must then determine not only when the texture changes but when its sampler state changes as well. * Not GM compatible. Those in favor of sampler states like Direct3D -----------------------------------------------------------Pros * GM: Studio and GM8.1 compatible * Much easier to perform automatic sprite batching and know when to flush the system. Cons * Extension below OpenGL3.3, so only newer hardware has it, otherwise it must be emulated, similarly to how it was being emulated before. * Slower only for OpenGL1, OpenGL3 will run the same as before. * More GPU interference in some cases, for a simple 2 texture example, one texture may have interpolation and the other may not, so more switching of states is required at runtime. It is also important that I clear up a misconception, while Direct3D9 and OpenGL1 started much differently, and I am referring to the API's themselves not our implementations, Direct3D11 and OpenGL4 are pretty consistently the same now. They both allow you to create the sampler states yourselves, but Direct3D11 lacks per-texture sampler information like OpenGL. http://msdn.microsoft.com/en-us/library/windows/desktop/ff476518%28v=vs.85%29.aspxThis also happens to match the resource limits for textures. You can only have 16,000 textures, consider 4 levels per texture you get about 4,000 unique sampler objects which fit directly with the resource limits of both Direct3D and OpenGL hardware. http://msdn.microsoft.com/en-us/library/windows/desktop/ff819065%28v=vs.85%29.aspxhttps://anteru.net/2013/05/02/2119/
|
|
« Last Edit: July 16, 2014, 02:12:25 am by Robert B Colton »
|
Logged
|
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.
|
|
|
TheExDeus
|
|
Reply #3 Posted on: July 16, 2014, 04:55:26 am |
|
|
Joined: Apr 2008
Posts: 1860
|
Sampler objects are tied to texture units right? So can't you just create 1 sampler object, tie that to texture unit 0, and change it's parameters with texture_set_ functions? Because normally you cannot use more than one texture in GM or ENIGMA. If you want to use more than one, then you must use custom shader, in which case you can allow more samplers to be made and modified.
And about the slowdown - why exactly is GL1 slower? If you cached it, then it shouldn't ever change during runtime unless manually changed. So there should be 0 performance degradation, unless calling a function of "if (changed == false) return;" somehow reduces performance.
I personally don't really care. OGL still allows you to use both - if you bind sampler 0, then you disable sampler objects and it uses texture data. So it's totally optional. You can keep it like it is for 99% of the time, and if the user wants to use sampler objects, then you can allow it (by creating new functions, like sampler_set_filtering, sampler_create etc.).
|
|
|
Logged
|
|
|
|
Goombert
|
|
Reply #4 Posted on: July 16, 2014, 05:08:18 am |
|
|
Location: Cappuccino, CA Joined: Jan 2013
Posts: 2993
|
Sampler objects are tied to texture units right? So can't you just create 1 sampler object, tie that to texture unit 0, and change it's parameters with texture_set_ functions? Because normally you cannot use more than one texture in GM or ENIGMA. If you want to use more than one, then you must use custom shader, in which case you can allow more samplers to be made and modified. Sure, but that doesn't change the fact that studio and Direct3D9 come with a default of 8. And about the slowdown - why exactly is GL1 slower? If you cached it, then it shouldn't ever change during runtime unless manually changed. So there should be 0 performance degradation, unless calling a function of "if (changed == false) return;" somehow reduces performance. How much do you expect me to catch it exactly? I applied a changed to each one of the state groups implemented so far, and that brought back to before any of my changes. But it does not work when you consider the hypothetical below. https://github.com/RobertBColton/enigma-dev/blob/master/ENIGMAsystem/SHELL/Graphics_Systems/OpenGL1/GLtextures.cpp#L198Hypothetical: * You create your two textures. * You turn on interpolation * You bind texture 1 * You draw something * You bind texture 2 * You draw something * You bind texture 1 * You draw something If turning on interpolation registers a change and binding a texture returns it to unchanged, texture 1 will retain its interpolation, but texture 2 will not and remain completely unaffected for the duration of the program. I have not thought of a way of caching which is changed without caching the sampler state per-texture, which is even more hectic! I personally don't really care. OGL still allows you to use both - if you bind sampler 0, then you disable sampler objects and it uses texture data. So it's totally optional. You can keep it like it is for 99% of the time, and if the user wants to use sampler objects, then you can allow it (by creating new functions, like sampler_set_filtering, sampler_create etc.). Yes but the problem here is that Studio names their sampler functions texture_*, so how are you going to remain compatible and have texture functions that let you do things per-texture? For instance, texture_set_interpolation_ext could take either samplerid or textureid but they would all have the same parameters and there is no way to distinguish. You could override texture_set_interpolation to take texture id, but that is confusing as fuck to the user, especially when you add in wild functions like texture_set_sampler_enabled(); or the likes. I can't honestly think of a way now that they did that shit to do this nicely without it being a confusing clusterfuck.
|
|
« Last Edit: July 16, 2014, 05:11:57 am by Robert B Colton »
|
Logged
|
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.
|
|
|
Darkstar2
|
|
Reply #5 Posted on: July 16, 2014, 06:00:58 am |
|
|
Joined: Jan 2014
Posts: 1238
|
All this talk about the texturing and other above, does this concern only the 3D games ? So basically from the above there are far more cons than pros, and given majority of people make 2D games and don't use features above I guess everyone can expect a degradation of speed along the line....... and more coding......doesn't sound too appealing So thanks for specifying it only makes it easier to vote, only problem there is no option to vote none of the above. But you know it's hard really to judge without actual tests ranging from simple stuff to complex stuff to see if the hit is significant enough. Can't you make new OGL and D3D API entries, keeping OGL1, OGl3, and DX9 like they are, but adding other sets of the same but with the changes, so people can test performance and decide which to use ?
|
|
« Last Edit: July 16, 2014, 06:05:08 am by Darkstar2 »
|
Logged
|
|
|
|
TheExDeus
|
|
Reply #6 Posted on: July 16, 2014, 10:28:08 am |
|
|
Joined: Apr 2008
Posts: 1860
|
Sure, but that doesn't change the fact that studio and Direct3D9 come with a default of 8. Well I guess it's because the sampler is tied to texture unit by default. You can do the same. But I would love functions that actually allow using sampler objects as real objects. So you can in fact create them, set their parameters and bind them to a unit. Then bind different one to the same unit. Because right now the whole point of sampler objects actually disappears. Like the original idea was that you could have 2 sampler objects (linear and bilinear for example) and use both of them in all cases. So you only have to bind them if you wanted to draw something differently and you wouldn't have to actually change the states. If turning on interpolation registers a change and binding a texture returns it to unchanged, texture 1 will retain its interpolation, but texture 2 will not and remain completely unaffected for the duration of the program. I have not thought of a way of caching which is changed without caching the sampler state per-texture, which is even more hectic! This description is true only GL1 right? Because why in GL3 would texture change return it to unchanged? Binding a texture will not reset sampler. Sampler is bound to texture unit. If you set interpolation to texture unit 0, then all textures bound to texture unit 0 will have this interpolation. As we bind every texture to unit 0 by default, then you end up changing interpolation for all textures. So texture_set_interpolation_ext(0,somePrefix_bilinear) is the same as texture_set_interpolation(somePrefix_bilinear) (just like in your code). It's just that no looping is required (which I think is nice, considering Project Mario loops over every texture about 4 times per frame). I have not thought of a way of caching which is changed without caching the sampler state per-texture, which is even more hectic! But that is exactly what I mean. You haven't actually cached anything in that code right now. Whenever a texture changes, you apply EVERY possible texture state change (right now it's 7 glTexParameter calls). No wonder why it is a lot slower now, because texture changes can happen tens or hundreds of times a frame, and you just set the same parameters all these times. So in GL1 you have to takes these 7 parameters, put them in texture class, and check them whenever ApplyState() is called. So if no sampler is actually changed, then no glTexParameter calls will be made. This will most probably reduce all performance impact. It might actually speed up GL1, because now if the user manually update the sampler (like via texture_set_interpolation or texture_set_interpolation_ext), there will be no glTexParameter calls made if the new parameters are just like the old ones. This is how caching is done in shader system with uniforms. I guess you can implement as you want and I will just see how to optimize it later.
|
|
|
Logged
|
|
|
|
Goombert
|
|
Reply #7 Posted on: July 25, 2014, 11:47:24 pm |
|
|
Location: Cappuccino, CA Joined: Jan 2013
Posts: 2993
|
The pull request has been completed and brings all our systems to the same level, provides some nice cleanup and advanced features while also being Studio compatible. https://github.com/enigma-dev/enigma-dev/pull/770My suggestion is to merge it so that the current implementation is at least more complete and Studio compatible until we work out alternatives and other changes.
|
|
|
Logged
|
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.
|
|
|
|