LINUX.ORG.RU
ФорумGames

Gaussian blur shader


0

2

Нет, это не очередной постпроцесс-эффект. Я долго думал, куда эту тему запихнуть: вроде и OpenGL есть, но и назначение у неё немного другое... Будем считать, что это Shader Toy.

Консольная (!) прога, которая считает размывание по гауссу с помощью шейдров. Алгоритм самый что ни есть «лобовой» - суммирует все пиксели подряд, из-за чего сильно тупит на больших радиусах. Чтобы на больших радиусах считал нормально, пришлось прикрутить хитропопый алгоритм который включается опцией fast, но чуть-чуть теряет в качестве. Разумеется, потребуется карта, поддерживающая шейдры и не-mesa драйвер.

Программа для Unix систем (под Win не пойдёт). Увы, ГУИ нет, свистелок тоже нет, и возможно придется даже компилять. Но думаю, это будет интересно тем... кому интересно.

В архиве сборка под Linux 32 bit, и исходники для 64 битников - чтобы собрать самому. У этой программы нет зависимостей (разве что только от Х:). Скачать без рекламы, смс, регистрации, ожидания 60 секунд и матан-капчи можно отсюда: http://ompldr.org/vYmd2OQ

Что выдаёт эталонный бенчмарк у меня:

$ ./gauss image.jpg 500 out1.bmp
Renderer: GeForce 6600 LE/AGP/SSE2 (NVIDIA Corporation)
Driver: 2.1.2 NVIDIA 270.41.06
Time: 3.050000 sec

$ ./gauss image.jpg 500 out2.bmp fast
Renderer: GeForce 6600 LE/AGP/SSE2 (NVIDIA Corporation)
Driver: 2.1.2 NVIDIA 270.41.06
Time: 0.060000 sec

Обратите внимание на эффект от хитрого алгоритма:)

Желающие могут потестить свои карточки. Особенно интересно как покажут себя современные карты с 9000 универсальных шейдерных процессоров. Не советую запускать на Intel GMA. Х сервер падает замертво.

Как видно, на больших радиусах может проигрывать даже CPU (так как на CPU используют быстрое преобразование Фурье, которое мне писать просто лень). Немного странная формула гаусса (exp(-x*x*3.058)) возникла из-за того, что я коэффициенты рассчитал «в лоб» в Maxima, чтобы распределение давало в сумме 1.

P.S. Думаю, будет любопытно посмотреть, как консольная прожка размером 70 килобайт уделывает по производительности всякие ImageMagick'и:) Это только гаусс, но в принципе можно так сделать любой фильтр, например, создание превьюшек из 100500 фоток.

Я специально не вшивал шейдр в сырцы, чтобы желающие могли потестировать свои собственные фильтры или просто поэкспериментировать.

Там нет автоопределения размера картинки, вшито 1024х1024. Sorry... В SOIL размер картинки не выковыривался, потом придумаю что-нибудь.


Всем ****й

Зря только потратил время на чтение очередного продукта жизнедеятельность

anonymous ()
Ответ на: комментарий от anonymous

Development - это разработка а тут уже готовый проект:)

opencv_gpu — ускорение некоторых функций OpenCV за счет CUDA, создан при поддержке NVidia.

Нипотянет:( У мну же 6600

RPG ()
Ответ на: комментарий от anonymous

Не могу протестить эту библиотеку, зато нарыл исходник этого фильтра. У них общий алгоритм для всех kernel-фильтров:

    template <int ksize, typename T, typename D, typename B>
    __global__ void linearRowFilter(const DevMem2D_<T> src, PtrStep_<D> dst, int anchor, const B b)
    {
        typedef typename SmemType<T>::smem_t smem_t;

        __shared__ smem_t smem[BLOCK_DIM_Y * BLOCK_DIM_X * 3];

        const int x = BLOCK_DIM_X * blockIdx.x + threadIdx.x;
        const int y = BLOCK_DIM_Y * blockIdx.y + threadIdx.y;

        smem_t* sDataRow = smem + threadIdx.y * BLOCK_DIM_X * 3;

        if (y < src.rows)
        {
            const T* rowSrc = src.ptr(y);

            sDataRow[threadIdx.x                  ] = b.at_low(x - BLOCK_DIM_X, rowSrc);
            sDataRow[threadIdx.x + BLOCK_DIM_X    ] = b.at_high(x, rowSrc);
            sDataRow[threadIdx.x + BLOCK_DIM_X * 2] = b.at_high(x + BLOCK_DIM_X, rowSrc);

            __syncthreads();

            if (x < src.cols)
            {
                typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type sum_t;
                sum_t sum = VecTraits<sum_t>::all(0);

                sDataRow += threadIdx.x + BLOCK_DIM_X - anchor;

                #pragma unroll
                for(int i = 0; i < ksize; ++i)
                    sum = sum + sDataRow[i] * cLinearKernel[i];

                dst.ptr(y)[x] = saturate_cast<D>(sum);
            }
        }
    }
Тут и так всё понятно.

Особый же интерес вызывает:

#pragma unroll
for(int i = 0; i < ksize; ++i)
     sum = sum + sDataRow[i] * cLinearKernel[i];
Очень похоже что тоже в лоб считают.

RPG ()
./gauss image.jpg 500 out2.bmp fast
Renderer: Gallium 0.4 on NV98 (nouveau)
Driver: 2.1 Mesa 7.12-devel (git-d4fcf67)
nv50_screen_get_shader_param:197 - unknown PIPE_SHADER_CAP 19
Error while compiling shader blurx.frag: 0:15(6): error: type mismatch
0:18(25): error: Could not implicitly convert operands to relational operator
0:18(25): error: loop condition must be scalar boolean
0:20(13): error: Could not implicitly convert operands to arithmetic operator
0:21(15): error: Could not implicitly convert operands to arithmetic operator

можно писать баг репорт?

seed_stil ★★ ()
neko@gdetotut ~/Загрузки/GPGPU gauss $ ./gauss image.jpg 500 out1.bmp
Renderer: ATI Mobility Radeon HD 4500 Series  (ATI Technologies Inc.)
Driver: 3.3.11251 Compatibility Profile Context
Error while compiling shader blurx.frag: Fragment shader failed to compile with the following errors:
WARNING: 0:14: warning(#254) Signature matching could not take type conversions into account in implicit GLSL version number 110 Gauss
ERROR: 0:15: error(#160) Cannot convert from 'uniform float' to 'mediump int'
ERROR: error(#273) 1 compilation errors.  No code generated
snoopcat ★★★★★ ()

^^^ лузеры

$ nice --20 ./gauss image.jpg 500 out1.bmp
Renderer: GeForce GTS 450/PCI/SSE2 (NVIDIA Corporation)
Driver: 4.2.0 NVIDIA 290.06
Time: 0.150000 sec

$ nice --20 ./gauss image.jpg 500 out2.bmp fast
Renderer: GeForce GTS 450/PCI/SSE2 (NVIDIA Corporation)
Driver: 4.2.0 NVIDIA 290.06
Time: 0.020000 sec
anonymous ()
Ответ на: комментарий от seed_stil

> можно писать баг репорт? В шейдре есть циклы и вычисление экспоненты. Скорее всего ваша видеокарта их не поддерживает.

Даже если шейдр запустится на драйвере Mesa, он будет медленнее Software рендера.

WARNING: 0:14: warning(#254) Signature matching could not take type conversions into account in implicit GLSL version number 110 Gauss
ERROR: 0:15: error(#160) Cannot convert from 'uniform float' to 'mediump int'
ERROR: error(#273) 1 compilation errors. No code generated

Это уже интереснее. Тут похоже драйвер не может выполнить приведение типов. Поможет либо #version 120 в начале шейдра, либо принудительная типизация (надеюсь).

Вот патч: http://ompldr.org/vYmg0aQ

лузеры

нормальный результат для 450. У GTS 250 как ни странно лучше:)

RPG ()
Ответ на: комментарий от anonymous

Код кодом, бекдор бекдором, пошутили и хватит.

winddos ★★★ ()
Ответ на: комментарий от RPG

>В шейдре есть циклы и вычисление экспоненты. Скорее всего ваша видеокарта их не поддерживает.

совершенно точно поддерживает. А вот драйвер, видимо, нет. Но я не знаю кому по этому поводу плакаться...

Даже если шейдр запустится на драйвере Mesa, он будет медленнее Software рендера.

о_О. что?

seed_stil ★★ ()
Ответ на: комментарий от winddos

>Как ты чотко втулил отписавшимся выше этот милый бекдор. :3

ЛОЛшто?

совершенно точно поддерживает. А вот драйвер, видимо, нет. Но я не знаю кому по этому поводу плакаться...

Драйвер не поддерживает. У вас стоит nouveau, разрабатываемый сообществом, а nvidia между делом не торопится открывать спеки и выпускает свой бинарный драйвер. Так что качайте с офф сайта и будет вас счастье:)

о_О. что?

Самолично чуть не угробил ноут, на котором была Mesa этим шейдром.

RPG ()
Ответ на: комментарий от RPG

С патчем

$ ./gauss image.jpg 500 out1.bmp
Renderer: Mesa DRI Intel(R) Sandybridge Mobile  (Tungsten Graphics, Inc)
Driver: 2.1 Mesa 7.11.1
Time: 0.130000 sec

madgnu ★★★★★ ()
Ответ на: комментарий от seed_stil

>Пинч обычно примерно столько весит :)

Это ж под оффтопик

с патчем на нуво зависли иксы :)

Я ещё в нулевом посте предупреждал про Mesa. Поставьте себе нормальные дрова

Driver: 2.1 Mesa 7.11.1

Time: 0.130000 sec

Хотя вот опровержение...

RPG ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.