Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 5 123 ... LastLast
Results 1 to 10 of 42

Thread: How Expensive are redundant State Changes?

  1. #1
    Junior Member Newbie
    Join Date
    Oct 2000
    Posts
    25

    How Expensive are redundant State Changes?

    Title says it all really. Are redundant state changes (i.e. setting state that is already set) caught by the driver before causing a hardware flush? I kind of assume they are, so the only overhead in setting redundant state is the API call. Are there any situations where redundant state changes can be very bad?

    Cheers,

    Henry

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Sep 2000
    Location
    Santa Clara, CA
    Posts
    1,463

    Re: How Expensive are redundant State Changes?

    Don't send redundant state changes. Just don't.

    Either design your code to avoid them or wrap GL functions to mirror state in your app. Test whether you're doing a redundant state change, and if you are, don't call into GL.

    - Matt

  3. #3
    Junior Member Newbie
    Join Date
    Jul 2000
    Location
    Helsinki, Finland
    Posts
    15

    Re: How Expensive are redundant State Changes?

    Ok, deleted the previous answer since it was obviosly the wrong one.

    Since I'm now forced to write an state mirror layer now , I was wondering the reason why. I would quess that the OpenGL states are mirrored in the system memory for fast access, but the api-overhead and maybe some other faces are making the redundant changes noticeable slower than using own state checker?

    Well I had a somewhat working prototype for mirroring the states, so I quess it's time to dust it off and put it back to use

  4. #4
    Intern Contributor
    Join Date
    Aug 2000
    Location
    USA
    Posts
    99

    Re: How Expensive are redundant State Changes?

    They can end up being *very* bad, I know from experience. The last game I worked on I was brought in to rewrite the OpenGL engine. When I came on board the game was getting maybe 2 fps on a PIII/500 with GeForce256. When I got done writing the new engine for it the game would stay pegged at 60 fps on this same setup. The biggest thing I did as far as improving upon the old engine in terms of speeding things up was that the old one made redundant state changes up the yang-yang, and my new engine makes no redundant state changes. So yes, they can be *very* bad. Never do that!

  5. #5
    Junior Member Newbie
    Join Date
    Oct 2000
    Posts
    25

    Re: How Expensive are redundant State Changes?

    Thanks for the replies. I'd be interested in knowing, if possible, why they can be so bad.

    Thing being, I now may have to litter if..else clauses all around my renderer, or actually write a wrapper for GL, which I don't really want to have to do - adding another level of indirection to API calls doesn't seem like a good idea, but I will if redundant state changes turn out to be really bad.

    Cheers,

    Henry

  6. #6
    Junior Member Newbie
    Join Date
    Jul 2000
    Location
    Helsinki, Finland
    Posts
    15

    Re: How Expensive are redundant State Changes?

    Writing a wrapper for the needed state changes is probably better than just throwing a bunch of if statements around your code. First of all it's easier to read the code and you still must pass the information about the state around in some meaningfull way and a singleton type of class comes really handy for the job, if you use an object oriented language.

    As for adding another abstraction layer on top of OpenGL, well I quess it's pretty much inevitable, since in some ways even if you keep track of the state in your code it is no different than an abstraction layer from a functional point of view

    And obviously you probably don't need to mirror all the OpenGL states, just the ones you really need to keep track on. This should speed up the creation of the wrapper significantly since you can easily add later more states to be mirrored. You could also add functions that handle a group of state changes by once and to possibly reduce the number of case statements.

    - Janne

  7. #7
    Senior Member OpenGL Pro
    Join Date
    Sep 2000
    Location
    Santa Clara, CA
    Posts
    1,463

    Re: How Expensive are redundant State Changes?

    Every time you call what looks like a "simple" OpenGL function like glBlendFunc, the following would happen with a "typical" driver, not necessarily representative of all drivers:

    - You call into a function pointer table in opengl32.dll. This table jumps to the actual function in the driver.
    - The driver accesses the thread-local state to get the current GL context (GC). This uses direct access to OS data structures; it's cheap (1 instruction) on NT, but a little more expensive on 9x (3 instructions, I think).
    - The driver checks whether you are inside a Begin/End.
    - The driver checks whether the source blend factor is valid.
    - The driver checks whether the destination blend factor is valid.
    - The driver copies the src and dst blend factors into shadows inside the GC.
    - The driver sets a bit to indicate that some rasterization state has changed.

    Later, when you do a Begin, DrawElements, etc.:
    - The driver looks at what dirty bits are set.
    - If any dirty bits are set, the driver makes sure that it can still render in HW.
    - Because the rasterization dirty bit is set, the driver grabs all the rasterization state and munges it into the way the HW expects to be told how to do rasterization (often a packed bitfield or somesuch). The driver sends this to the HW.

    Variants include not setting a dirty bit and instead sending the state immediately to the HW, or not shadowing the state in the driver at all, but the summary is that a redundant state change is simply a bad thing.

    I haven't even considered the possibility of a stall inside the HW. We do a pretty good job of making sure that such stalls are minimal, but sometimes they still exist.

    If you avoid sending redundant states, on a typical driver, you will at avoid at least a check for Begin/End and an error check on each parameter. That by itself is a pretty nice savings.

    Most drivers don't actually look for redundant state changes explicitly because this would penalize smart apps that don't send redundant state changes to help dumb apps that do.

    - Matt

  8. #8
    Junior Member Regular Contributor
    Join Date
    Jan 2001
    Location
    Shanghai, China
    Posts
    155

    Re: How Expensive are redundant State Changes?

    I am not very clear about the wrapper Janne refered, how can those if-else statement be avoided? I must check the current value to see if I can skip setting it. Can you explain it a bit more?
    Does those switch state change cost heavily? something like glEnable*() and glDisable*().

    [This message has been edited by Nil_z (edited 01-17-2001).]
    End of transmission...

  9. #9
    Senior Member OpenGL Pro
    Join Date
    Sep 2000
    Location
    Santa Clara, CA
    Posts
    1,463

    Re: How Expensive are redundant State Changes?

    Also, when I'm talking about wrappers, it's nothing more complicated than:

    Code :
    void MyBlendFunc(GLenum src, GLenum dst)
    {
      static GLenum curSrc = GL_ONE;
      static GLenum curDst = GL_ZERO;
     
      if ((src == curSrc) && (dst == curDst)) {
        return;
      }
      curSrc = src;
      curDst = dst;
      glBlendFunc(src, dst);
    }
    But you can do other clever things too. Here are two examples I can think of:

    Code :
    void MyEnableLights(int n)
    {
      int i;
      static int lastN = 0;
     
      if (n < lastN) {
        for (i = n; i < lastN; i++) {
          glDisable(GL_LIGHT0 + i);
        }
      } else if (n > lastN) {
        for (i = lastN; i < n; i++) {
          glEnable(GL_LIGHT0 + i);
        }
      }
    }
     
    enum BLEND_MODE {
      NO_BLENDING,
      TRANSPARENCY,
      TRANSPARENCY_ADDITIVE,
      ADDITIVE,
      SRC_TIMES_DST,
      BLEND_MODE_COUNT,
    };
     
    GLenum blendModeTable[BLEND_MODE_COUNT][2] = {
      GL_ONE, GL_ZERO,
      GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
      GL_SRC_ALPHA, GL_ONE,
      GL_ONE, GL_ONE,
      GL_ZERO, GL_SRC_COLOR,
    };
     
    static void MyBlendFunc(BLEND_MODE mode)
    {
      static BLEND_MODE lastMode = NO_BLENDING;
     
      if (mode == lastMode) {
        return;
      }
     
      if (mode == NO_BLENDING) {
        glDisable(GL_BLEND);
      } else {
        if (lastMode == NO_BLENDING) {
          glEnable(GL_BLEND);
        }
        glBlendFunc(blendModeTable[mode][0], blendModeTable[mode][1]);
      }
      lastMode = mode;
    }
    I take no responsibility for any bugs in this code. You get the idea, though. OpenGL is a low-level graphics API. That gives you the freedom to wrap any higher-level API you like on top of it, and that higher-level API can take responsibility for ensuring that there are no redundant state changes.

    - Matt

  10. #10
    Senior Member OpenGL Pro
    Join Date
    Feb 2000
    Location
    France
    Posts
    1,118

    Re: How Expensive are redundant State Changes?

    Originally posted by mcraighead:
    I take no responsibility for any bugs in this code.
    Got an error on this line:

    GLenum blendModeTable[BLEND_MODE_COUNT][2] =

    'BLEND_MODE_COUNT': undeclared identifier



    Eric

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •