eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › cpu shading by sse intrinsics
Ilość wypowiedzi w tym wątku: 8

  • 1. Data: 2014-06-28 12:48:05
    Temat: cpu shading by sse intrinsics
    Od: firr <p...@g...com>

    w moim rasteryzerze mam blog do flat shadingu
    trojkatów od 4rech swiateł - wyglada on wyjatkowo niechlujnie moim zdaniem ale do
    końca nie wiem co
    z nim zrobic



    // input: float x1, y1, z1, x2, y2, z2, x3, y3, z3;


    static float3 lightDir1= {0.2, -1.6, -1.7 };
    static float3 lightDir2 = {0.5, -0.7, 20.3 };
    static float3 lightDir3 = {-0.5,-0.3, -0.6 };
    static float3 lightDir4 = {-0.5, 1.3, 0.6 };

    static float3 lightColor1= {.4, .414, .515 };
    static float3 lightColor2 = {.4145, .451, .543 };
    static float3 lightColor3 = {.584, .51414, .43 };
    static float3 lightColor4 = {.41, .44, .3414 };


    float3 u = {x2-x1, y2-y1, z2-z1 };
    float3 v = {x3-x2, y3-y2, z3-z2 };

    float3 normal = cross_(u,v);

    // normal.x = (y2-y1)*(z3-z2) - (z2-z1)*(y3-y2);
    // normal.y = (z2-z1)*(x3-x2) - (x2-x1)*(z3-z2);
    // normal.z = (x2-x1)*(y3-y2) - (y2-y1)*(x3-x2);

    normalize(&normal);

    float s1 = dot(normal, lightDir1);
    float s2 = dot(normal, lightDir2);
    float s3 = dot(normal, lightDir3);
    float s4 = dot(normal, lightDir4);


    if(s1<0) s1=0;
    if(s2<0) s2=0;
    if(s3<0) s3=0;
    if(s4<0) s4=0;


    int b = (color&0x000000ff);
    int g = (color&0x0000ff00)>>8;
    int r = (color&0x00ff0000)>>16;

    float lr= .1 + (s1*lightColor1.x + s2*lightColor2.x + s3*lightColor3.x+
    s4*lightColor4.x);
    float lg= .1 +(s1*lightColor1.y + s2*lightColor2.y + s3*lightColor3.y+
    s4*lightColor4.y);
    float lb= .1 + (s1*lightColor1.z + s2*lightColor2.z + s3*lightColor3.z+
    s4*lightColor4.z);


    r*=lr;
    g*=lg;
    b*=lb;

    if(r>255) r=255;
    if(g>255) g=255;
    if(b>255) b=255;

    return rgb(b,g,r);

    chodzi o dwie rzeczy
    1) jak ew przyspieszyc czy ladniej to zapisac z poziomu c
    2) jak przepisac to i przyspieszyc przy pomocy sse intrinsics (uzywam mingw gcc 4.7
    wiec tak zeby poszlo pod tym kompilatorem)

    glownie chodzi o ta drugą rzecz, nie mam moze nawet w sumie az tak duzo czasu na to
    ;/ ale z drugiej strony troche podlubac by sie przydalo ;\


  • 2. Data: 2014-06-29 12:46:22
    Temat: Re: cpu shading by sse intrinsics
    Od: firr <p...@g...com>

    uzyskalem przez zapytanie na innym forum taki kod


    #include <pmmintrin.h>

    struct FourVec3s { __m128 x; __m128 y; __m128 z; };
    struct FourTris { FourVec3s a; FourVec3s b; FourVec3s c; __m128i colors; };

    // transposed
    static FourVec3s lightDirs = {{0.2, 0.5, -0.5, -0.5},
    {-1.6,-0.7,-0.3, 1.3},
    {-1.7, 20.3,-0.6, 0.6}};

    // transposed
    static FourVec3s lightColors = {{.4, .4145, .584, .41 },
    {.414, .451, .51414,.44},
    {.515, .543, .43, .3414}};

    static __m128 modelRight = {1.0, 0.0, 0.0, 0.0};
    static __m128 modelUp = {0.0, 1.0, 0.0, 0.0};
    static __m128 modelDir = {0.0, 0.0, 1.0, 0.0};
    static __m128 modelPos = {0.0, 0.0, 0.0, 1.0};


    static inline __m128 splatX(__m128 v) { return
    _mm_shuffle_ps(v,v,_MM_SHUFFLE(0,0,0,0)); }
    static inline __m128 splatY(__m128 v) { return
    _mm_shuffle_ps(v,v,_MM_SHUFFLE(1,1,1,1)); }
    static inline __m128 splatZ(__m128 v) { return
    _mm_shuffle_ps(v,v,_MM_SHUFFLE(2,2,2,2)); }
    static inline __m128 add(__m128 l, __m128 r) { return _mm_add_ps(l, r); }
    static inline __m128 sub(__m128 l, __m128 r) { return _mm_sub_ps(l, r); }
    static inline __m128 mul(__m128 l, __m128 r) { return _mm_mul_ps(l, r); }
    static inline __m128 and(__m128 l, __m128 r) { return _mm_and_ps(l, r); }
    static inline __m128 less(__m128 l, __m128 r) { return _mm_cmplt_ps(l, r); }
    static inline __m128 dot(const FourVec3s &l, const FourVec3s &r) { return
    add(add(mul(l.x,r.x), mul(l.y,r.y)), mul(l.z,r.z)); }

    // unpack 8 bit RgbaRgbaRgbaRgba into 32-bit RRRR gggg or bbbb
    static inline __m128i unpackR(__m128i iv) { return
    _mm_unpacklo_epi16(_mm_unpacklo_epi8(iv,_mm_setzero_
    si128()),_mm_setzero_si128()); }
    static inline __m128i unpackG(__m128i iv) { return
    _mm_unpackhi_epi16(_mm_unpacklo_epi8(iv,_mm_setzero_
    si128()),_mm_setzero_si128()); }
    static inline __m128i unpackB(__m128i iv) { return
    _mm_unpacklo_epi16(_mm_unpackhi_epi8(iv,_mm_setzero_
    si128()),_mm_setzero_si128()); }
    static inline __m128 intsToFloats(__m128i iv) { return _mm_cvtepi32_ps(iv); }
    static inline __m128i floatToInts(__m128 fv) { return _mm_cvttps_epi32(fv); }
    static inline __m128i packAndSaturate32To8(__m128i r ,__m128i g, __m128i b, __m128i
    a) { return _mm_packs_epi16(_mm_packs_epi32(r,g),_mm_packs_epi32
    (b,a)); }


    static inline FourVec3s normalizeFourVec3s(const FourVec3s &v) {
    __m128 length = _mm_sqrt_ps(add(add( mul(v.x,v.x), mul(v.y,v.y)), mul(v.z,v.z)
    ));
    FourVec3s result = { _mm_div_ps(v.x,length), _mm_div_ps(v.y,length),
    _mm_div_ps(v.z,length) };
    return result;
    }

    __m128i Shade4Triangles(const FourTris &tris) {
    __m128 x1 = add(add(add( mul(sub(tris.a.x, splatX(modelPos)),
    splatX(modelRight)), // (*triangle).a.x - modelPos.x)*modelRight.x +
    mul(sub(tris.a.y, splatY(modelPos)),
    splatY(modelRight))), // ((*triangle).a.y - modelPos.y)*modelRight.y +
    mul(sub(tris.a.z, splatZ(modelPos)),
    splatZ(modelRight))), // ((*triangle).a.z - modelPos.z)*modelRight.z) +
    splatX(modelPos));
    // modelPos.x
    __m128 y1 = add(add(add( mul(sub(tris.a.x, splatX(modelPos)), splatX(modelUp)),
    mul(sub(tris.a.y, splatY(modelPos)), splatY(modelUp))),
    mul(sub(tris.a.z, splatZ(modelPos)), splatZ(modelUp))),
    splatY(modelPos));
    __m128 z1 = add(add(add( mul(sub(tris.a.x, splatX(modelPos)), splatX(modelDir)),
    mul(sub(tris.a.y, splatY(modelPos)), splatY(modelDir))),
    mul(sub(tris.a.z, splatZ(modelPos)), splatZ(modelDir))),
    splatZ(modelPos));
    __m128 x2 = add(add(add( mul(sub(tris.b.x, splatX(modelPos)),
    splatX(modelRight)),
    mul(sub(tris.b.y, splatY(modelPos)),
    splatY(modelRight))),
    mul(sub(tris.b.z, splatZ(modelPos)),
    splatZ(modelRight))),
    splatX(modelPos));
    __m128 y2 = add(add(add( mul(sub(tris.b.x, splatX(modelPos)), splatX(modelUp)),
    mul(sub(tris.b.y, splatY(modelPos)), splatY(modelUp))),
    mul(sub(tris.b.z, splatZ(modelPos)), splatZ(modelUp))),
    splatY(modelPos));
    __m128 z2 = add(add(add( mul(sub(tris.b.x, splatX(modelPos)), splatX(modelDir)),
    mul(sub(tris.b.y, splatY(modelPos)), splatY(modelDir))),
    mul(sub(tris.b.z, splatZ(modelPos)), splatZ(modelDir))),
    splatZ(modelPos));
    __m128 x3 = add(add(add( mul(sub(tris.c.x, splatX(modelPos)),
    splatX(modelRight)),
    mul(sub(tris.c.y, splatY(modelPos)),
    splatY(modelRight))),
    mul(sub(tris.c.z, splatZ(modelPos)),
    splatZ(modelRight))),
    splatX(modelPos));
    __m128 y3 = add(add(add( mul(sub(tris.c.x, splatX(modelPos)), splatX(modelUp)),
    mul(sub(tris.c.y, splatY(modelPos)), splatY(modelUp))),
    mul(sub(tris.c.z, splatZ(modelPos)), splatZ(modelUp))),
    splatY(modelPos));
    __m128 z3 = add(add(add( mul(sub(tris.c.x, splatX(modelPos)), splatX(modelDir)),
    mul(sub(tris.c.y, splatY(modelPos)), splatY(modelDir))),
    mul(sub(tris.c.z, splatZ(modelPos)), splatZ(modelDir))),
    splatZ(modelPos));

    FourVec3s normal;
    normal.x = sub( mul(sub(y1,y1),sub(z3,z2)), mul(sub(z2,z1),sub(y3,y2)) );
    normal.y = sub( mul(sub(z2,z1),sub(x3,x2)), mul(sub(x2,x1),sub(z3,z2)) );
    normal.z = sub( mul(sub(x2,x1),sub(y3,y2)), mul(sub(y2,y1),sub(x3,x2)) );
    normal = normalizeFourVec3s(normal);

    __m128 s1234 = dot(normal, lightDirs);
    s1234 = and(s1234, less(_mm_setzero_ps(), s1234));

    __m128 l = add(_mm_set_ps1(0.1f), add(add( mul(s1234,lightColors.x),
    mul(s1234,lightColors.y)), mul(s1234,lightColors.z)));

    __m128i r = floatToInts(mul(l,intsToFloats(unpackR(tris.colors))
    ));
    __m128i g = floatToInts(mul(l,intsToFloats(unpackG(tris.colors))
    ));
    __m128i b = floatToInts(mul(l,intsToFloats(unpackB(tris.colors))
    ));

    return packAndSaturate32To8(r,g,b,_mm_setzero_si128());
    }

    aczkolwiek czeka mnie z tym mała 'rozkminka' bo nie wszystko jest jasne


  • 3. Data: 2014-06-30 10:42:48
    Temat: Re: cpu shading by sse intrinsics
    Od: Wojciech Muła <w...@g...com>

    On Saturday, June 28, 2014 12:48:05 PM UTC+2, firr wrote:
    > chodzi o dwie rzeczy
    >
    > 1) jak ew przyspieszyc czy ladniej to zapisac z poziomu c

    Nie licz za każdym razem normalnej, ani jej nie normalizuj (to
    pierwiastek i trzy dzielenia - dwie najwolniejsze operacje na CPU).
    Shader nie powinien liczyć normalnej, a jedynie intensywność światła.
    Mieszasz odpowiedzialności i wychodzi sieczka.

    > 2) jak przepisac to i przyspieszyc przy pomocy sse intrinsics (uzywam mingw gcc 4.7
    wiec tak zeby poszlo pod tym kompilatorem)

    Najpierw dobrze napisz wersję skalarną, potem zastanawiaj się jak
    ją przyspieszyć SIMD-ami. Zresztą wątpliwe, czy zrobisz to lepiej niż
    kompilator, popatrz na http://locklessinc.com/articles/vectorize/.

    w.


  • 4. Data: 2014-06-30 12:16:29
    Temat: Re: cpu shading by sse intrinsics
    Od: firr <p...@g...com>

    W dniu poniedziałek, 30 czerwca 2014 10:42:48 UTC+2 użytkownik Wojciech Muła napisał:
    > On Saturday, June 28, 2014 12:48:05 PM UTC+2, firr wrote:
    >
    > > chodzi o dwie rzeczy
    >
    > >
    >
    > > 1) jak ew przyspieszyc czy ladniej to zapisac z poziomu c
    >
    >
    >
    > Nie licz za każdym razem normalnej, ani jej nie normalizuj (to
    >
    > pierwiastek i trzy dzielenia - dwie najwolniejsze operacje na CPU).
    >
    > Shader nie powinien liczyć normalnej, a jedynie intensywność światła.
    >
    > Mieszasz odpowiedzialności i wychodzi sieczka.
    >
    >
    >
    > > 2) jak przepisac to i przyspieszyc przy pomocy sse intrinsics (uzywam mingw gcc
    4.7 wiec tak zeby poszlo pod tym kompilatorem)
    >
    >
    >
    > Najpierw dobrze napisz wersję skalarną, potem zastanawiaj się jak
    >
    > ją przyspieszyć SIMD-ami. Zresztą wątpliwe, czy zrobisz to lepiej niż
    >
    > kompilator, popatrz na http://locklessinc.com/articles/vectorize/.
    >
    >

    nie przypuszczam zeby bylo to watpliwe, ztcw te wektoryzery potrafia wykonac ledwie
    szczatkowe
    operacje

    co do przepisywania na razie chyba porobie troszke prostsze testy (bo w tych
    wiekszych troche sie gubie) - zobacze np czy zwykle obracanie wektorow coskolwiek
    przyspiesza
    (nie spodziewam sie za wiele ale trzeba sprawdzic)

    cos w stylu - pseudokod roboczy

    float modelRight_x;
    float modelRight_y;
    float modelRight_z;

    float modelUp_x;
    float modelUp_y;
    float modelUp_z;

    float modelDir_x;
    float modelDir_y;
    float modelDir_z;


    float normal_x[100*1000];
    float normal_y[100*1000];
    float normal_z[100*1000];

    float n_x[100*1000];
    float n_y[100*1000];
    float n_z[100*1000];

    for(int i=0; i<100*1000; i++)
    {
    normal_x[i] = n_x[i]*modelRight_x + n_y[i]*modelRight_y + n_z[i]*modelRight_z;
    normal_y[i] = n_x[i]*modelUp_x + n_y[i]*modelUp_y + n_z[i]*modelUp_z;
    normal_z[i] = n_x[i]*modelDir_x + n_y[i]*modelDir_y + n_z[i]*modelDir_z;
    }

    float4 modelRight_4x = populate(modelRight_x);

    for(int i=0; i<100*1000; i+=4)
    {
    add_ps(

    normal_x[i] = add_ps(
    mul_ps(n_x, modelRight_x),
    mul_ps(n_y, modelRight_y) ),
    mul_ps(n_z, modelRight_z))

    normal_y[i] = add_ps(
    mul_ps(n_x, modelUp_x),
    mul_ps(n_y, modelUp_y) ),
    mul_ps(n_z, modelUp_z))

    normal_z[i] = add_ps(
    mul_ps(n_x, modelDir_x),
    mul_ps(n_y, modelDir_y) ),
    mul_ps(n_z, modelDir_z))

    }


  • 5. Data: 2014-06-30 12:27:53
    Temat: Re: cpu shading by sse intrinsics
    Od: firr <p...@g...com>

    ps co do liczeni normalnej to nie jest takie jasne bo skladowanie i czytanie z
    megabajtów normalnych troche trwa gdy tymczasem shading robie juz po clippingu i
    potrzebuje tylko co poniektórych (dla obecnego tie fightera okolo 15-25% ale dla
    normalnych scen raczej mniej) - robilem wczesniej wstepne testy i liczenie on-the-fly
    bylo jakby lepsze (na dokladniejsze testy na razie nie mam sily)

    uczenie sie podstaw sse jest troche meczace , mam na przyklad taka niejasnosc, czy
    jest jakis intrinsic/opkod do wczytywania intow/floatow do m128 nie z pamieci ale
    jako immediate?


  • 6. Data: 2014-07-02 01:20:51
    Temat: Re: cpu shading by sse intrinsics
    Od: firr <p...@g...com>

    co jeszcze moge powiedziec o takim programowaniu
    tymi intrinsicami

    podobaja mi sie takie rzeczy jak

    _mm_and_ps(values, _mm_cmplt_ps(zeros, values));

    czyli takie porownania jakich nie ma w normalnym asmie (a chyba szkoda, (?)) tj nie
    rozgaleziajace kodu a zwracajace 'maski' ktorych pozniej mozna uzyc

    wtady mozna pisac bezifowo rozne takie wyrazenia jak

    a += 17 & (b>10);

    co jest rownowazne
    if(b>10) a+=17;

    w c tez to mozna napisac (jako ze wyzej jest to wlasnie napisane) ale nie wiem czy w
    starym asemblerze (tym bez cmov) dalo sie to zapisac bezifowo - warunek ustawia niby
    flagi ale nie
    pamietam czy byla komenda ktora populowala flage na np cale slowo jedynek itp

    jeszcze inna uwaga, ogolnie jak nawyknac 9juz chyba nawyklem) to to tzw wertykalne
    kodowanie w intrisincowym sse jest zupelnie proste za wyjatkiem tego ze trzeba
    ukladac te dane i akurat jak ja czytam ten kod wyzej to mozna sie pogubic
    na jakiej ilosci danych operuje konkretny operand
    (chyab trzeba sie troche do tego przyzwyczaic tak jak do wskaznikow)

    nie che mi sie tu tlumaczyc o co mi chodzi ale mw o to

    __m128 s1234 = dot(normal, lightDirs);

    wiadomo ze to robi dota normalnej z lightDirs
    i ustawia wynik jako s1234 ale ile dokladnie tego to bierze i jak nie jest dla mnie
    jakos natychmiastowo jasne

    (to jest wertykalny kod wiec wiadomo ze dziala na paczkach po 4 ale tutaj jest chyba
    podwojnie wertykalny - wlasnie nawet nie wiem czy takich zapisow nie nalezy unikac,

    chozi tez o pewna kwestie dotyczaca rozkladu danych
    wiadomo ze dane musza byc by to tak nazwac zgrupowane w poprzek np

    {x[100], y[100], z[100]}
    zamiast
    {x,y,z}[100]

    (ta skladnia nie jest glupia nie wiem czy nie przydalaby sie nawet tak by okreslac
    rozmaite layouty a pozniej uzywac x[i] do abstrakcyjnego latania po tych layoutach)

    ale pytanie jest czy grupowac w male paczki po cztaery w poprzek tj
    {x[4], y[4], z[4]}[25]
    czy zupelnie w poprzek {x[100], y[100], z[100]}

    zupelnie w poprzek wydaje sie senswniejsze ale
    ten paczkowy layout ma pewne 'zalety' czy tez po prostu wlasnosci, mianowicie takie
    ze zeby np
    napisac takiego podwojnie wertylkalnego dota
    wystarczy podac dwa wskazniki tj na jedna paczke i na drugą dot(&a, &b) a bez
    rozkladu paczkowego trzeba podac ich szesc dot(&x,&y,&z, &x2,&y2,&z2) - chociaz ja
    optuje chyba raczej za tym drugim zapisem jest o wiele bardziej czytelny










  • 7. Data: 2014-07-02 18:12:25
    Temat: Re: cpu shading by sse intrinsics
    Od: Edek <e...@g...com>

    Szarym od mżawki świtem Mon, 30 Jun 2014 01:42:48 -0700, Wojciech Muła
    wyrzucił pustą ćwiartkę i oznajmił:

    > On Saturday, June 28, 2014 12:48:05 PM UTC+2, firr wrote:
    >> chodzi o dwie rzeczy
    >>
    >> 1) jak ew przyspieszyc czy ladniej to zapisac z poziomu c
    >
    > Nie licz za każdym razem normalnej, ani jej nie normalizuj (to pierwiastek
    > i trzy dzielenia - dwie najwolniejsze operacje na CPU). Shader nie
    > powinien liczyć normalnej, a jedynie intensywność światła.
    > Mieszasz odpowiedzialności i wychodzi sieczka.

    W tej jego grze rpg matematyka wymagałaby długiego rozwijania skilla,
    ze względu na brak ajtemów dających +1000000 do inteligencji. W sumie
    fajnie się patrzy na kogoś, kto bardzo chce używać sse a nie ma pojęcia
    o kosztach podstawowych operacji matematycznych, o inwencji w przekształcaniu
    i upraszczaniu obliczeń nie wspominając. Słodki żuczek, niech sobie leży
    na pleckach i macha nóżkami, zaczynam zmieniać podejście do jego blogowania
    na grupie.

    --
    Edek


  • 8. Data: 2014-07-02 20:13:29
    Temat: Re: cpu shading by sse intrinsics
    Od: firr <p...@g...com>


    ale jestem kurna zmeczony..

    ogolnie moim doraznym celem byloby przepisanie
    mojego softwarowego pipeline na sse i zobaczenie
    czy to przyspieszy [pisze o tym bo jest to ciekawy
    temat na grupe aczkolwiek z tego powodu ze jest za
    mala raczej marne szanse by ktos podjal i rozwinal
    temat] - gdyby to np dzialalo dwa razy
    szybciej dla duzej rozdzielczosci (tam gdzi emam teraz 40-60ms)
    to by bylo cudownie tyle ze na to o ile wiem raczej nie
    ma szans (jako ze tego typu program to raczej przeplyw ramu
    a obliczenia sa w sumi naskórkowe - garstka mnozen kilka
    ifów - jeszcze troche ifów - i na koniec nieregularne
    (trójkątne nomen omen) petelki, - w tych petelkach sa
    dzielenia, (jadno na kazda scanline potrzebne do wyznaczania
    nachyleń ale w sumie nie wiem czy tych dzielen na wspolczesnych
    kompach trzeba unikac (kiedys owszem ztcw byly naprawde
    wolne) - sa to w sumie dzilenia przez inta tak ze
    moglbym to stablicowac i sprawdzic... tak ze ogolnie
    rzecz biorac po przepisaniu tego (czesciowym bo samego
    rysowania trojkatow raczej sie nie da), pewnie skonczy
    sie labo na przyspieszeniu rzedu 20% albo wogole
    (ze wzgledu na pewne dodatkowe kopiowania ktore trzeba
    bedzie zrobic na uzytek sse) - zagadnienie w sumie ciekawe
    jak ktos lubi niskopoziomowe kodowanie

strony : [ 1 ]


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: