XNA Creators Club Online
Page 1 of 1 (17 items)
Sort Posts: Previous Next

Code in Pixel shader can be faster than code in the Vertex shader?

Last post 05-08-2008 8:44 PM by Shawn Hargreaves. 16 replies.
  • 05-06-2008 2:18 PM

    Code in Pixel shader can be faster than code in the Vertex shader?

    I've got a lot of ideas and theory's floating around my head.  I finally decided to prove/disprove one. But I got inconclusive results.

    In thery and in practice, Per pixel lighting is more expensive than per vertex.  Or so I always thought, until the logical side of my brain tried to induce wrinkles in my knowledge.  I was thinking that there might actually be a threshold where per pixel lighting, could be faster than per vertex.  And if this is true, then it holds to reason that other algorithyms could hold to the same pattern.

    The Test: I took the Skinned model sample and changed it to draw 10 versions of dude.  I added a new technique to draw per pixel, because the default is per vertex.  Then when holding down a key on the keyboard, I would use the per pixl technique and when not holding the key, it was the per vertex technique.

    The results: No change in frame rate!  I could see the diffence on the models and strangly, per vertex on dude actually looked a little better than per pixel. (Per pixel looked more accurate though.)

    Interperation: So there was no spike in framerate or for that matter, even a hickup.  So I couldn't disprove my theory nor confirm it. But the results make me believe that code in the pixel shader can be less of a burden on the GPU when the item being draw has a large number of vertices that come close to the number of pixels being generated.  (100 ~ 80)

    So please correct me if I'm wrong, but if this is true, then when drawing items that appear in the far distance, (where number of vertices is greater than number of pixels generated), per pixel lighting is actually faster.

     

  • 05-06-2008 2:38 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    If your model contains more vertices than it covers pixels, yes, it will usually be faster to do your work in the pixel shader.

    That's generally not a good place to be, though: such a high poly model is going to be very expensive no matter how you write your shader, and is also likely to have aliasing problems. If you get to the point where you have significantly more than one triangle per pixel, that's usually a sign you should be switching to a lower detail version of the model.

    In your case it is also possible that the reason you didn't measure any framerate change is you might have been CPU bound at the time. If you are CPU bound, changing GPU performance won't make any difference to your measured framerate.
    XNA Framework Developer - blog - homepage
  • 05-06-2008 2:59 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    Thanks for the reply Shawn.  The main point I was trying to get across was to dispel the notion that Per Pixel lighting is slower than per vertex.  I've seen many posts/websights that make this blanket statement. (To the point, I took it as a truth.)

    The models I'll be working with will be around 2,000 vertices vs. dude at 15,000 or so. I was just using dude because I remembered it has a large vertice count.  I'm sure that I was CPU bound but it's also possible that the dude model is right at the threshold for the same preformance in both techniques. 

    I was thinking that the GPU only calls the Pixel shader once per pixel, irregardless of how many vertices may be used to generate that pixel. 

  • 05-07-2008 9:12 AM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    gorky:

    Thanks for the reply Shawn.  The main point I was trying to get across was to dispel the notion that Per Pixel lighting is slower than per vertex.  I've seen many posts/websights that make this blanket statement. (To the point, I took it as a truth.)

    In general the blanket statement holds though, since you typically have many more pixels than vertices. Other factors than model complexity may account for the vertex lighting's apparent slowness, like whether or not your graphics card does hardware vertex processing (many Intel card do not) and the ratio of vertex processing units vs pixel processing units on your card. Since pixel processing typically requires more work anyway and much of the processing has shifted from vertices to pixels, many cards are actually better equiped for pixels calculations.

  • 05-07-2008 10:51 AM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    Current-generation graphics cards have unified shader processing units that handle both vertex and pixel shaders (and geometry shaders).
    Microsoft DirectX/XNA MVP
  • 05-07-2008 12:12 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    ShawMishrak:
    Current-generation graphics cards have unified shader processing units that handle both vertex and pixel shaders (and geometry shaders).

    What I'm really curious about, is what happens in the following scenario:

    Normally a quad with four vertices would generate multiple pixels on the screen.  But what if the quad is far enough away (or just simply tiny to begin with) that it will generate only one pixel?

    Do the pixel shaders have to wait until the vertex shaders are done?  Or do they process data as it's rasterized?

    Does the rasterizer make the pixel shader reprocess the pixel for each vertice and then combine the results?  Or does the rasterizer combine all the vertex shader outputs via averaging and have the pixel shader process just once?

  • 05-07-2008 12:22 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    gorky:

    Do the pixel shaders have to wait until the vertex shaders are done?  Or do they process data as it's rasterized?



    GPUs are heavily pipelined and run lots of things in parallel. The vertex shader will typically be processing vertices for the next triangle (or even one ten or twenty further on) while the pixel shader is finishing up an earlier triangle.

    The pixel shader always runs exactly once per pixel (or more precisely, four times per 2x2 block of pixels, since it must shader four pixels in parallel in order to compute gradient information for mipmapping).
    XNA Framework Developer - blog - homepage
  • 05-07-2008 5:48 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    Shawn Hargreaves:

    GPUs are heavily pipelined and run lots of things in parallel. The vertex shader will typically be processing vertices for the next triangle (or even one ten or twenty further on) while the pixel shader is finishing up an earlier triangle.

    The pixel shader always runs exactly once per pixel (or more precisely, four times per 2x2 block of pixels, since it must shader four pixels in parallel in order to compute gradient information for mipmapping).

    Thanks for the info.  I had thought that the pixel shader was run just once for each pixel, but I didn't know for sure. 

    So this means the rasterizer somehow combines vertex shader outputs when needed.  Magic stuff there!  This is very facinating when you consider that, given a large model/landscape patch, not all vertices may be processed before some pixels are given to the pixel shader.  How it knows when it is ok to do this, is beyond me.

  • 05-07-2008 6:56 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    gorky:

    So this means the rasterizer somehow combines vertex shader outputs when needed. 


    Of course. How else would it know where the middle pixel of a triangle was located? You need all three of the triangle vertices to determine that position.


    gorky:

    This is very facinating when you consider that, given a large model/landscape patch, not all vertices may be processed before some pixels are given to the pixel shader.  How it knows when it is ok to do this, is beyond me.



    This is actually very simple:
    • Shade all three vertices for triangle #1
    • Shade all pixels covered by the resulting screenspace triangle
    • Shade all three vertices for triangle #2
    • Shade all pixels covered by the resulting screenspace triangle
    • repeat until all triangles have been drawn

    XNA Framework Developer - blog - homepage
  • 05-07-2008 7:58 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    Shawn Hargreaves:

    Of course. How else would it know where the middle pixel of a triangle was located? You need all three of the triangle vertices to determine that position.

    That is the easy case. 

    I'm talking about something like a normal.  Each Vertice will send its normal along.  In the case of all vertices of a face, they share the same normal, but in the situation where many faces of a model resolve to one pixel, there should/could be many differing normal values being sent from the vertex shader.  Then in the pixel shader, it uses them to calculate per pixel lighting.  How does the rasterizer combine this data?


    Shawn Hargreaves:


    This is actually very simple:
    • Shade all three vertices for triangle #1
    • Shade all pixels covered by the resulting screenspace triangle
    • Shade all three vertices for triangle #2
    • Shade all pixels covered by the resulting screenspace triangle
    • repeat until all triangles have been drawn


    I meant something more complex:

    • Triangle 1 resolves to pixel 2,2 (first)
    • Triangle 2 resolves to pixel 2,2 (second time)
    • Triangle 3 resolves to pixel 2,3
    • Triangle 4 resolves to pixel 2,2 (Third time)
    • Triangle 5 resolves to pixel 3,2
    • Triangle 6 resolves to pixel 2,2 (fourth time)

    The above situation has a part of a model resolve to three pixels.  Given the posibility that any vertice, from any face could in theory and practice, resolve to any pixel, I'm baffled by how the hardware does this. 

    Now extrapolate my simple example into a complex model.  It is very possible that the first vertice processed by the vertex shader can be a neighbor of the last vertice processed by the vertex shader.  They may be 15,000 vertices apart.  Yet because they are neighbors, they may resolve to the same pixel.  Yet the pixel shader was already called for the shared pixel very early!

  • 05-07-2008 8:19 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    That's not how it works. Pixels aren't covered by fractional numbers of triangles: each triangle either covers one pixel entirely, or it covers zero pixels. There's never any kind of averaging or blending from one triangle to another.

    (well, technically multisampling kind of does that, but it basically just expands each pixel out into two or four, then does the same binary triangle is or isn't covering each sample location decision)
    XNA Framework Developer - blog - homepage
  • 05-07-2008 8:46 PM In reply to

    Re: Code in Pixel shader can be faster than code in the Vertex shader?

    So in the most extreme case, a small scaled model that has 10,000 triangles is sitting around 9999 units away on the z.  It's sitting right next to the far clipping plane.   For this example, all 10,000 triangles will only show up as one pixel in this scenerio.  

    That means that only the triangles that cover the entire pixel, can possibly be sent to the pixel shader.  So it's very possible that the model doesn't show up at all, because no single triangle covers the entire pixel, right?

    It is possible that a few triangles could generate total coverage of a pixel, thereby getting thier data sent to the pixel shader.  Who wins?  The first triangle that covers 100% of the pixel and all other later processed triangles that meet the same criteria have thier results discarded?