On 11/06/17 07:59, Jacob Lifshay wrote:
On Sat, Jun 10, 2017 at 3:25 PM Jose Fonseca <jfons...@vmware.com <mailto:jfons...@vmware.com>> wrote:

    I don't see how to effectively tack triangle setup into the vertex
    shader: vertex shader applies to vertices, where as triangle setup and
    bining applies to primitives.  Usually, each vertex gets transformed
    only once with llvmpipe, no matter how many triangles refer that vertex.
       The only way to tack triangle setup into vertex shading would be if
    you processed vertices a primitive at a time.  Of course one could put
    an if-statement to skip reprocessing a vertex that already was
    processed, but then you have race conditions, and no benefit of
    inlining.

I was mostly thinking of non-indexed vertices.

    And I'm afraid that tacking rasterization too is one those things that
    sound great on paper, quite bad in practice.  And I speak from
    experience: in fact llvmpipe had the last step of rasterization bolted
    on the fragment shaders for some time.  But we took it out because it
    was _slower_.

    The issue is that if you bolt on to the shader body, you either:

    - inline in the shader body code for the maxmimum number of planes that
    (which are 7, 3 sides of triangle, plus 4 sides of a scissor rect), and
    waste cpu cicles going through all of those tests, even when most of the
    time many of those tests aren't needed

    - or you generate if/for blocks for each place, so you only do the
    needed tests, but then you have branch prediction issues...

    Whereas if you keep rasterization _outside_ the shader you can have
    specialized functions to do the rasterization based on the primitive
    itself: (is the triangle fully inside the scissor, you need 3 planes, if
    the stamp is fully inside the triangle you need zero).  Essentially you
    can "compose" by coupling two functions calls: you call a rasterization
    function that's especiallized for the primitive, then a shading function
    that's specialized for the state (but not depends on the primitive).

    It makes sense: rasterization needs to be specialized for the primitive,
    not the graphics state; where as the shader needs to be specialized for
    the state.

I am planning on generating a function for each primitive type and state combination, or I can convert all primitives into triangles and just have a function for each state. The state includes stuff like if a particular clipping/scissor equation needs to be checked. I did it that way in my proof-of-concept code by using c++ templates to do the code duplication: https://github.com/programmerjake/tiled-renderer/blob/47e09f5d711803b8e899c3669fbeae3e62c9e32c/main.cpp#L366

I'm not sure there will be enough benefits of iniline to compensate the time spent on compiling 2**7 variants of each shader to cope with all possible incoming triangles..

    And this is just one of those non-intuitive things that's not obvious
    until one actually does a lot of profiling, a lot of experimentation.
    And trust me, lot of time was spent fine tuning this for llvmpipe (not
    be me -- most of rasterization was done by Keith Whitwell.)  And by
    throwing llvmpipe out of the window and starting a new software
    rendering from scratch you'd be just subscribing to do it all over
    again.

    Whereas if instead of starting from scratch, you take llvmpipe, and you
    rewrite/replace one component at a time, you can reach exactly the same
    destination you want to reach, however you'll have something working
    every step of the way, so when you take a bad step, you can measure
    performance impact, and readjust.  Plus if you run out of time, you have
    something useful -- not yet another half finished project, which quickly
    will rot away.

In the case that the project is not finished this summer, I'm still planning on working on it, just at a reduced rate. If all else fails, we will at least have a up-to-date spir-v to llvm converter that handles the glsl spir-v extensions.

    Regarding generating the spir-v -> scalar llvm, then do whole function
    vectorization, I don't think it's a bad idea per se.  If was I writing
    llvmpipe from scratch today I'd do something like that.  Especially
    because (scalar) LLVM IR is so pervasive in the graphics ecosistem
    anyway.

    It was only after I had tgsi -> llvm ir all done that I stumbled into
    http://compilers.cs.uni-saarland.de/projects/wfv/ .

    I think the important thing here is that, once you've vectorized the
    shader, and you converted your "texture_sample" to
    "texture_sample.vector8", and your "output_merger" intrinsics to
    "output_merger.vector8", or you log2/exp2, you then slot the fine tuned
    llvmpipe code for texture sampling and blending and math, as that's were
    your bottle necks tend to be.  Because if you plan to write all texture
    sampling from scratch then you need a time/clone machine to complete
    this in a summer; and if just use LLVM's / standard C runtime's
    sqrt/log2/exp2/sin/cos then it would be dead slow.

I am planning on using c++ templates to help with a lot of the texture sampler code generation -- clang can convert it to llvm ir and then I can inline it into the appropriate places. I think that all of the non-compressed image formats should be pretty easy to handle that way, as they are all pretty similar (bits packed into a long word or members of a struct). I can implement interpolation on top of the functions to load and unpack the image elements from memory. I'd estimate that, excluding the compressed texture formats, I'd need less than 10k lines and maybe a week or two to implement it all. (Glad I don't have to implement that in C.)

But how will 8/16-bit integer SIMD operations be generated in this process? Because if you stick with floating point then you'll never catch up with llvmpipe for texturing. And this is the bottleneck for most practical applications.

I am planning on compiling fdlibm with clang into
llvm ir, then running my vectorization algorithm on all the functions. LLVM has a spot where you can tell it that you have optimized vectorized math intrinsics, I could add them there, or implement another lowering pass to convert the intrinsics to function calls, which can then be inlined. Hopefully, that will save most of the work needed to implement vectorized math functions.

I don't see how a whole function vectorization function will transform something like this

  http://www.netlib.org/fdlibm/e_log.c

into something like this


https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/auxiliary/gallivm/lp_bld_arit.c#n3451

Vectorization is only a (actually small) part of this: one doesn't need or want to deal with subnormals, and graphics APIs have higher tolerance in precision, and since this is a software renderer you don't want to be more precise than you have to. Furthermore the fdlibm code don't seem amenable to vectorization -- they are full of control flow if/for loops. Not to mention: they used _double_ precision...


I have to say I'm missing the plot here. Is the objective to make a fast software renderer, or just another software renderer? Because in some cases you justify some several decision in the pursuit of performance, whereas in others you make design decisions in spite of poor performance.


I can certainly relate to the wish of doing cool stuff (and IMO software renderers is one of the most fun stuff to work on in graphics), and I don't expect you to take grunt work (that's why employment exists.) But I just find it a pity that a better overlap between cool/fun and useful wasn't found. We already have 4 software renderer in Mesa, two of them fast. And to me it seems we're putting ourselves in a lose-lose situation: if you're not successful (ie this new software renderer doesn't reach critical mass and eventually dies down when you stop working), you just wasted your time and we missed an opportunity to leverage your skills. If you are successfull we have yet another software renderer in Mesa competing for attention...

On the flip side, there are some interesting ideas you propose I'm curious to see how they pan out.

Jose
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to