Texture-matrix not working on some systems
  • Acolyte of the Butterfly
    Acolyte of the Butterfly
    Daytona675x
    Posts: 109 from 2013/12/5
    During developing AceOfHearts for MorphOS I ran into another TinyGL issue (or most likely a driver issue).

    Looks like modifications of the GL_TEXTURE matrix are not supported by every system. On my Radeon9000 based setup all works well, but on Yasu's Radeon 9600 for example any modification of the texture-matrix is apparently ignored.

    The effect looks like this:

    texture_matrix_bug.jpg

    It should be obvious what SHOULD happen: the texture-matrix is set up to scale the s/t coordinates of the respective textures to cover the target area completely.

    You may use the game's demo version to test that.

    As a workaround I added a tooltype, HQ_TEXTURES=1.

    If this is set, then texture-matrix scaling is used and it may result in those buggy effects.

    If this tooltype is 0 or commented out, then the textures are internally scaled up to be POT and the identity texture matrix is used, therefore it will work everywhere at a loss of quality.

    The code fragment is simple:
    Code:
    glMatrixMode(GL_TEXTURE);
    glLoadMatrixf(uv_factor_matrix.m);

    where the matrix consists out of 16 floats forming a simple scaling matrix.
    As being said: it works well as expected on my Radeon9000 (and on other systems too, like Windows).

    EDIT: typo, my system is equipped with a Radeon9000, not 9200

    [ Editiert durch Daytona675x 29.01.2014 - 05:57 ]
  • »28.01.14 - 10:48
    Profile Visit Website
  • Paladin of the Pegasos
    Paladin of the Pegasos
    Yasu
    Posts: 1724 from 2012/3/22
    From: Stockholm, Sweden
    It's on my G5. A Radeon 9600 Pro 256 VRAM. It's the same on both DVI outputs.

    [Edit] It's my screen dump btw.

    [ Edited by Yasu 28.01.2014 - 13:07 ]
    AMIGA FORUM - Hela Sveriges Amigatidning!
    AMIGA FORUM - Sweden's Amiga Magazine!

    My MorphOS blog
  • »28.01.14 - 12:06
    Profile Visit Website
  • MorphOS Developer
    cyfm
    Posts: 537 from 2003/4/11
    From: Germany
    Quote:

    Yasu schrieb:
    It's on my G5. A Radeon 9600 Pro 256 VRAM. It's the same on both DVI outputs.

    [Edit] It's my screen dump btw.

    [ Edited by Yasu 28.01.2014 - 13:07 ]


    This is some bug/missing feature in the r300 driver which affects all r300 based cards afaik.
  • »29.01.14 - 18:06
    Profile Visit Website
  • Paladin of the Pegasos
    Paladin of the Pegasos
    Yasu
    Posts: 1724 from 2012/3/22
    From: Stockholm, Sweden
    @pega-1

    Are these problems being worked on? Just curious :-)
    AMIGA FORUM - Hela Sveriges Amigatidning!
    AMIGA FORUM - Sweden's Amiga Magazine!

    My MorphOS blog
  • »29.01.14 - 23:30
    Profile Visit Website
  • Acolyte of the Butterfly
    Acolyte of the Butterfly
    Daytona675x
    Posts: 109 from 2013/12/5
    Quote:

    pega-1 schrieb:
    This is some bug/missing feature in the r300 driver which affects all r300 based cards afaik.



    Pretty crucial core feature that's missing here!
    The funny part is that it works on super-antique cards like the Radeon 9000...
    So yes, just like Yasu I'm curious to know if / when that's going to be fixed.
  • »30.01.14 - 06:53
    Profile Visit Website
  • Caterpillar
    Caterpillar
    Posts: 33 from 2013/6/20
    Quote:

    the texture-matrix is set up to scale the s/t coordinates



    Hello
    Not sure what you are trying to do...
    But why dont you scale yourself the texture coordinate (I mean applying your matrix to each UV manually) ??

    Alain Thellier
  • »30.01.14 - 07:45
    Profile Visit Website
  • Acolyte of the Butterfly
    Acolyte of the Butterfly
    Daytona675x
    Posts: 109 from 2013/12/5
    Quote:

    thellier schrieb:
    Not sure what you are trying to do...
    But why dont you scale yourself the texture coordinate (I mean applying your matrix to each UV manually) ??



    Actually it doesn't matter what I want to try :-)
    But well, you answered your question yourself already: "manually".

    I don't want to multiply each UV "manually".
    I want to use the core feature GL_TEXTURE-matrix that last not least was invented to avoid such manual multiplications.

    It boils down to this:

    1. the UV-scaling itself needs to be done because many textures in my project aren't POT and need to be made POT during run-time on devices that don't support NPOT.

    2. if the underlying system doesn't support NPOT then such a texture is blowed up to the next POT-size and pixels are either scaled (that's the fallback I currently use, results in poorer quality) or not (that is the texture's significant pixels remain top-left and the additional POT-pixels are filled with 0, then the texture-object is marked as being POTified and a UV scaling factor is calculated).

    3. the point is: I don't know during compile-time which textures end up POTified and which don't and if POTified, which algorithm was chosen. In my layouts I asume the original assets size and UVs.

    4. so I could either chose the unelegant variant you propose and multiply every UV I use by the factors of the bound texture manually.
    Bad idea, for several reasons. One being that the UVs may be floats or ints or whatever. Another being that the stride between the UVs is varying. So I would have to implement either a smart and slow version that handles all possible cases or a ton of variants that handle each case. And I would have to call that before issuing a draw-command.
    Oh, but wait, there's a pitfall: I will have to be really careful when I want to reuse a UV-array for another draw-call. Was it already multiplied or not?
    You see: manually multiplying is a really bad idea.

    5. therefore I want to use the texture-matrix. This solves all those issues. If it would work.

    I know that modifying the texture-matrix for each such texture is not the most performant way to draw things. But it is not more performant to do UV-scaling manually neither (at least not on systems that cannot do NPOT... :-) , and the texture-matrix scaling is only done if it really needs to be done, of course).
    Of course it would be best if the assets would all be prepared in a prescaled way and the layout-definitions would use the "pre-scaled" UVs in the first place. But this again makes no sense in my case, since a) the performance gain is neglectable and b) it would make designing the game more time-consuming, it is easier to just use pictures as the artist designed them and be done and c) most systems (including AOS4 compositing) I target can do NPOT, actually MorphOS is the only one that can't :-) .

    [ Editiert durch Daytona675x 30.01.2014 - 09:37 ]
  • »30.01.14 - 08:34
    Profile Visit Website
  • Caterpillar
    Caterpillar
    Posts: 33 from 2013/6/20
    @all
    POT = power of two texture
    NPOT = non power of two texture
    He certainly use rectangular textures for a gui

    >MorphOS is the only one that can't .
    So all is said : It is up to you to find another way ....
    This is why I talked about "manually" doing it

    @ Daytona675x
    Excuse me but "Tu te noye dans un verre d'eau"
    Doing it manually is only
    having/testing 2 flags : card_cant_do_npot uvarray->already_scaled

    if(card_cant_do_npot)
    if(!uvarray->already_scaled)
    for each U V in uvarray
    multiply U V with 2 floats resizeu resizev (no need for a full matrix)

    Alain
  • »30.01.14 - 09:41
    Profile Visit Website
  • Acolyte of the Butterfly
    Acolyte of the Butterfly
    Daytona675x
    Posts: 109 from 2013/12/5
    @thellier

    Quote:

    So all is said : It is up to you to find another way ....

    As being said:
    I already have a workaround as a a fallback that doesn't need to use manual multiplying (at the cost of some image quality).
    And no, actually it's not up to me, it's up to the driver-coder to fix it.

    Quote:

    He certainly use rectangular textures for a gui

    In this particular case, yes. Although my textures are most often rectangular regardless of what I do with them :-)
    And again: it doesn't matter what I want to do with it. A core feature is missing, period. We got a bug here.

    Quote:


    Doing it manually is only
    having/testing 2 flags : card_cant_do_npot uvarray->already_scaled
    if(card_cant_do_npot)
    if(!uvarray->already_scaled)
    for each U V in uvarray
    multiply U V with 2 floats resizeu resizev (no need for a full matrix)



    Obviously you didn't get the point:
    I want to use a core GL feature for that task.
    Your little snippet missed the most important parts of the real world implementation, and it missed most of the important implicatins I already mentioned above. It is over-simplified and therefore no valid argument. This is a more valid snippet:

    Code:

    if(uv_array_type==GL_FLOAT) DoFloatScaleImplementation(pointer,count,stride,factors);
    else if(uv_array_type==GL_INT) DoIntScaleImplementation(pointer,count,stride,factors);
    else if(uv_array_type==GL_SHORT) DoShortScaleImplementation(pointer,count,stride,factors);
    else if(uv_array_type==GL_DOUBLE) DoDoubleScaleImplementation(pointer,count,stride,factors);

    void DoFloatScaleImplementation(void *data,unsigned int count,int stride,const float *uv_scale)
    {
    float *uv=(float*)data;
    for(unsigned int t=0;t<count;++t) {
    uv[0]*=uv_scale[0];
    uv[1]*=uv_scale[1];
    ((unsigned char*)uv)+=stride;
    }
    }

    // repeat for each variant of use templates in the first place


    Also you need to do additional management. Of course at the end it is at first a check against a boolean "already-multiplied".
    But in the real world you have to add such a flag to your array-management code.

    In contrast to all that:

    by using the texture-matrix all that hazzle is gone, all you need to do is to add a flag/factors to the texture-info (which you'd have to do with the manual approach too) and wrap BindTexture to catch that info and modify the texture-matrix if necessary. Done. No need to flag or modify texcoord-arrays. Plus you can do more with it (it is a matrix, you can also do translation in combination with scaling to zoom a texture, for example).

    By the way: your approach won't work when the texcoord-array is const (which is not a very unlikely situation!).
    In such a case you'd have to make a copy of everything. Which would also imply that your scaler changes the tex-coord-pointer... Brilliant idea :-P

    No thanks, your approach has way too many side-effects if you really think about its consequences, is too limited and needs too many manual tweaks all over the code. I prefer to choose the commands GL offers for that task.

    Yours may be the way to go in a HelloWorld-program, but not in a real world application.

    Oh, here is a real world example where the texture-matrix was incredibly useful, and it had nothing to do with "rectangular UI textures" :
    When I wrote the 3D engine for that game here back in 2009 it had to run on iPhone1 hardware. And there was a heavy RAM limit. Therefore the UVs of all models and the terrain were SHORTs. Guess what: without texture-matrix-scaling this wouldn't have been possible, because the texture-matrix multiplication is applied after the arrays are submitted to the GL, it is applied in terms of floats.
    But thanks to texture-matrix-scaling the shorts could effectively hold a 16bit float.

    Cheers, hope you learned something ;-)

    Anyway, I think even thellier agrees that we got a bug in the driver here and that it would be nice if that gets fixed, so people can decide for themselfs to use that feature if they find it useful for whatever reason which other people probably don't realize at first sight.

    Is this going to be fixed and if so, when? Would be nice to know, because if it's going to be fixed with the next MorphOS-version I could default to this rendering path if I detect a that new OS-version. Currently I default to the ugly workaround and you can toggle via tooltype :-(
  • »30.01.14 - 10:07
    Profile Visit Website
  • Caterpillar
    Caterpillar
    Posts: 33 from 2013/6/20
    >even thellier agrees that we got a bug in the driver
    Of course I agree but as I am not a Morphos dev you can only wait an eventual driver fix...

    As we say here (ironically but it happen in real world too) about query for program fix "Expliquez nous ce qui vous manque dans ce programme et nous on vous dira comment s'en passer" (Please let explain us the missing feature and will teach how to live forewer without it)
    [Damn I realize that I am beginning to answer this way too ;-P ]

    BTW I am also waiting for glTexCoordPointer(4,GL_FLOAT,...); to be implemented for Wazp3D perspective-texturing :-)

    >UVs of all models and the terrain were SHORTs
    Of course I agree data packing is a good usage for texture-matrix .... but that was not the initial question

    Cheers
    Alain Thellier
  • »30.01.14 - 13:10
    Profile Visit Website
  • Acolyte of the Butterfly
    Acolyte of the Butterfly
    Daytona675x
    Posts: 109 from 2013/12/5
    Quote:

    thellier schrieb:
    Of course I agree but as I am not a Morphos dev you can only wait an eventual driver fix...
    BTW I am also waiting for glTexCoordPointer(4,GL_FLOAT,...); to be implemented for Wazp3D perspective-texturing :-)


    Well, we all are used to wait in Amiga-land (and I mean all flavors by that) :-)
    That reminds me that I have to write a large bug-report regarding compositing-engine-flaws on R200-hardware on AOS4... ;-)

    Quote:

    Of course I agree data packing is a good usage for texture-matrix .... but that was not the initial question

    That's right, it just came back to my mind during typing, should help to underline the importance of that feature :-)

    But the other points are answers to the question, why to prefer the texture-matrix over manual multiplying in general and why I want it in my case, to sum it up:

    - it is a core feature of GL.
    - it works with every texcoord-type out of the box.
    - it works with every array-type / stride out of the box.
    - you don't need to track if an array was already multiplied.
    - it works with const arrays, no need to create a copy and change array-pointers etc.
    - the key is that it works transparently, only the BindTexture-Wrapper has to do something for it to work.
    - plus it offers additional features a simple mul-loop can't do (just as an example, it could be used to procedurally generate and use texture-atlases without the rest of the program knowing the final UVs, thanks to the possibility to also translate the matrix)

    In my scenery, which I described in post #7, this is clearly the very best approach, because this scaling is used to compensate the non-existance of NPOT-texture-support. It would be insane to approach this manually, you'd end up adding lots of code and complexity, additional dependencies and potential source for problems or performance penalties on other systems, only to support that very rare case (well, not so rare on MorphOS ;-) ).
    A simple five-line-multiplication-loop is just not enough to handle this in a correct way.

    Cheers,
    Daniel
  • »30.01.14 - 13:56
    Profile Visit Website