<div dir="auto"><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Feb 14, 2017 12:18 AM, "Nicolai Hähnle" <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>> wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="quoted-text">On 13.02.2017 17:54, Jacob Lifshay wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
the algorithm i was going to use would get the union of the sets of live<br>
variables at the barriers (union over barriers), create an array of<br>
structs that holds them all, then for each barrier, insert the code to<br>
store all live variables, then end the for loop over tid_in_workgroup,<br>
then run the memory barrier, then start another for loop over<br>
tid_in_workgroup, then load all live variables.<br>
</blockquote>
<br></div>
Okay, sounds reasonable in theory.<br>
<br>
There are some issues, like: how do you actually determine live variables? If you're working off TGSI like llvmpipe does today, you'd need to write your own analysis for that, but in a structured control flow graph like TGSI has, that shouldn't be too difficult.<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">I was planning on using the spir-v to llvm translator and never using tgsi. I could implement the pass using llvm coroutines, however, I'd need to have several additional passes to convert the output; it might not optimize all the way because we would have the switch on the suspend point index still left. Also, according to the docs from llvm trunk, llvm doesn't support reducing the space required by using the minimum size needed to store all the live variables at the suspend point with the largest space requirements, instead, it allocates separate space for each variable at each suspend point: <a href="http://llvm.org/docs/Coroutines.html#areas-requiring-attention">http://llvm.org/docs/Coroutines.html#areas-requiring-attention</a></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I'd still recommend you to at least seriously read through the LLVM coroutine stuff.<br>
<br>
Cheers,<br>
Nicolai<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="quoted-text">
Jacob Lifshay<br>
<br>
On Feb 13, 2017 08:45, "Nicolai Hähnle" <<a href="mailto:nhaehnle@gmail.com" target="_blank">nhaehnle@gmail.com</a><br></div><div class="elided-text">
<mailto:<a href="mailto:nhaehnle@gmail.com" target="_blank">nhaehnle@gmail.com</a>>> wrote:<br>
<br>
    [ re-adding mesa-dev on the assumption that it got dropped by accident ]<br>
<br>
    On 13.02.2017 17:27, Jacob Lifshay wrote:<br>
<br>
                I would start a thread for each cpu, then have each<br>
        thread run the<br>
                compute shader a number of times instead of having a<br>
        thread per<br>
                shader<br>
                invocation.<br>
<br>
<br>
            This will not work.<br>
<br>
            Please, read again what the barrier() instruction does: When the<br>
            barrier() call is reached, _all_ threads within the<br>
        workgroup are<br>
            supposed to be run until they reach that barrier() call.<br>
<br>
<br>
        to clarify, I had meant that each os thread would run the<br>
        sections of<br>
        the shader between the barriers for all the shaders in a work group,<br>
        then, when it finished the work group, it would go to the next work<br>
        group assigned to the os thread.<br>
<br>
        so, if our shader is:<br>
        a = b + tid;<br>
        barrier();<br>
        d = e + f;<br>
<br>
        and our simd width is 4, our work-group size is 128, and we have<br>
        16 os<br>
        threads, then it will run for each os thread:<br>
        for(workgroup = os_thread_index; workgroup < workgroup_count;<br>
        workgroup++)<br>
        {<br>
            for(tid_in_workgroup = 0; tid_in_workgroup < 128;<br>
        tid_in_workgroup += 4)<br>
            {<br>
                ivec4 tid = ivec4(0, 1, 2, 3) + ivec4(tid_in_workgroup +<br>
        workgroup * 128);<br>
                a[tid_in_workgroup / 4] = ivec_add(b[tid_in_workgroup /<br>
        4], tid);<br>
            }<br>
            memory_fence(); // if needed<br>
            for(tid_in_workgroup = 0; tid_in_workgroup < 128;<br>
        tid_in_workgroup += 4)<br>
            {<br>
                d[tid_in_workgroup / 4] = vec_add(e[tid_in_workgroup / 4],<br>
        f[tid_in_workgroup / 4]);<br>
            }<br>
        }<br>
        // after this, we run the next rendering or compute job<br>
<br>
<br>
    Okay good, that's the right concept.<br>
<br>
    Actually doing that is not at all straightforward though: consider<br>
    that the barrier() might occur inside a loop in the shader.<br>
<br>
    So if you implemented that within the framework of llvmpipe, you'd<br>
    make a lot of people very happy: it would allow finally adding<br>
    compute shader support to llvmpipe. Mind you, that in itself would<br>
    already be a pretty decent-sized project for GSoC!<br>
<br>
    Cheers,<br>
    Nicolai<br>
<br>
</div></blockquote>
<br>
</blockquote></div><br></div><div class="gmail_extra" dir="auto">Jacob Lifshay</div></div></div>