inventor 0 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба есть контроллер кортекс, подключенный к нему через FPGA дисплей вывожу картинку старого формата XBM на экран монитора DMAнет и выводить нужно попиксельно экран долго рисует, что ожидаемо /** * Вывести файл XBM (ширина должна делиться на 8!!!) */ void bitmap_draw_xbm(const char* bmp, int width, int height) { u32 k = 0; u8 m = 0, pix; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { pix = bmp[k]; pix = (pix >> m) & 1; display_put_pixel(x, DISPLAY_HEIGTH - y, pix == 0? 0xFFFF: 0); m++; if (m == 8) { k++; m = 0; } } } } формат XBM такой, если кто не знает: #define x_width 512 #define x_height 512 static char x_bits[] = { 0x28, 0x8a, 0xe2, 0x3f, 0xfe, 0xf3, каждый бит в байте и сдвигать выводя попиксельно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 37 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба Восемь раз подряд один и тот же адрес памяти читать "pix = bmp[k];" в цикле по x не накладно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
inventor 0 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба это я уже убрал и сделал так: for (int y = 0; y < height; y++) { for (int x = 0; x < width; x += 8, k++) { pix = *(bmp + k); p0 = pix & 1; p1 = pix & 2; p2 = pix & 4; p3 = pix & 8; p4 = pix & 16; p5 = pix & 32; p6 = pix & 64; p7 = pix & 128; display_put_pixel(x, DISPLAY_HEIGTH - y, p0 == 0? 0xFFFF: 0); display_put_pixel(x + 1, DISPLAY_HEIGTH - y, p1 == 0? 0xFFFF: 0); display_put_pixel(x + 2, DISPLAY_HEIGTH - y, p2 == 0? 0xFFFF: 0); display_put_pixel(x + 3, DISPLAY_HEIGTH - y, p3 == 0? 0xFFFF: 0); display_put_pixel(x + 4, DISPLAY_HEIGTH - y, p4 == 0? 0xFFFF: 0); display_put_pixel(x + 5, DISPLAY_HEIGTH - y, p5 == 0? 0xFFFF: 0); display_put_pixel(x + 6, DISPLAY_HEIGTH - y, p6 == 0? 0xFFFF: 0); display_put_pixel(x + 7, DISPLAY_HEIGTH - y, p7 == 0? 0xFFFF: 0); } } но все равно скорость не достаточная Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zeal0t 0 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 30 minutes ago, inventor said: это я уже убрал и сделал так: for (int y = 0; y < height; y++) { for (int x = 0; x < width; x += 8, k++) { pix = *(bmp + k); p0 = pix & 1; p1 = pix & 2; p2 = pix & 4; p3 = pix & 8; p4 = pix & 16; p5 = pix & 32; p6 = pix & 64; p7 = pix & 128; display_put_pixel(x, DISPLAY_HEIGTH - y, p0 == 0? 0xFFFF: 0); display_put_pixel(x + 1, DISPLAY_HEIGTH - y, p1 == 0? 0xFFFF: 0); display_put_pixel(x + 2, DISPLAY_HEIGTH - y, p2 == 0? 0xFFFF: 0); display_put_pixel(x + 3, DISPLAY_HEIGTH - y, p3 == 0? 0xFFFF: 0); display_put_pixel(x + 4, DISPLAY_HEIGTH - y, p4 == 0? 0xFFFF: 0); display_put_pixel(x + 5, DISPLAY_HEIGTH - y, p5 == 0? 0xFFFF: 0); display_put_pixel(x + 6, DISPLAY_HEIGTH - y, p6 == 0? 0xFFFF: 0); display_put_pixel(x + 7, DISPLAY_HEIGTH - y, p7 == 0? 0xFFFF: 0); } } но все равно скорость не достаточная основное время тратится скорее всего вот тут display_put_pixel можно посмотреть как это реализовано и как то оптимизировать. например выводить не по 1 точке а сразу 8 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
inventor 0 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба Just now, Zeal0t said: можно посмотреть как это реализовано и как то оптимизировать. например выводить не по 1 точке а сразу 8 это просто запись в память (*((volatile u32 *) (addr))) = col; вероятно сама плис долго выводит решили сделать 2 адресных пространства 1-е попиксельное рисование в цветах 2-е вывожу двойное слово где каждый бит- ч/б пиксель так будет быстрее работать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 232 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 2 часа назад, inventor сказал: экран долго рисует, что ожидаемо А что такое display_put_pixel() - предлагаете телепатам угадать? Очередная угадайка.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 37 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба Восемь раз display_put_pixel вызывается и каждый раз аргумент вычисляется (DISPLAY_HEIGTH - y): есть гарантия что не 8 раз одно и то же? Из цикла по x - долой... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amaora 24 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 22 minutes ago, inventor said: (*((volatile u32 *) (addr))) = col; Зачем volatile? pix = *bmp++; *outpix++ = (pix & 1) ? 0xFFFF : 0; *outpix++ = (pix & 2) ? 0xFFFF : 0; *outpix++ = (pix & 4) ? 0xFFFF : 0; *outpix++ = (pix & 8) ? 0xFFFF : 0; *outpix++ = (pix & 16) ? 0xFFFF : 0; *outpix++ = (pix & 32) ? 0xFFFF : 0; *outpix++ = (pix & 64) ? 0xFFFF : 0; *outpix++ = (pix & 128) ? 0xFFFF : 0; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 232 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 2 часа назад, amaora сказал: Зачем volatile? А зачем такая куча условных выражений? Ведь каждое - это ветвление, а значит особенные тормоза. Цитата pix = *bmp++; *outpix++ = (pix & 1) ? 0xFFFF : 0; *outpix++ = (pix & 2) ? 0xFFFF : 0; *outpix++ = (pix & 4) ? 0xFFFF : 0; *outpix++ = (pix & 8) ? 0xFFFF : 0; *outpix++ = (pix & 16) ? 0xFFFF : 0; *outpix++ = (pix & 32) ? 0xFFFF : 0; *outpix++ = (pix & 64) ? 0xFFFF : 0; *outpix++ = (pix & 128) ? 0xFFFF : 0; ТС как будто сделал целью сделать как можно более тормозной код. Только такое объяснение нахожу этой куче лишних переменных и ветвлений... Да и у ТСа вроде при бите==0 должно получаться 0xFFFF, а у Вас - наоборот. Если у ТСа внутри этого секретного макроса display_put_pixel() (и макроса ли?) действительно именно такие записи в память, то всё делается много лаконичнее и быстрее: int i = ~*bmp++; *outpix++ = i << 31 >> 31 & 0xFFFF; *outpix++ = i << 30 >> 31 & 0xFFFF; *outpix++ = i << 29 >> 31 & 0xFFFF; ... При полной оптимизации это должно дать всего по 3 ассемблерных команды на каждый бит. А вообще низкоуровневая оптимизация делается низкоуровневыми средствами - ассемблером. Так можно сделать ещё оптимальнее. PS: А дальше надо смотреть - а зачем 32-битные записи, если старшие 16 бит содержимого памяти всегда ==0? Может хватит 16-битных записей? И, если внешняя шина к FPGA у ТСа 16-разрядная, то это может дать существенный прирост скорости. Вобщем - при таком уровне информации, когда ТС 90% данных утаил трудно что-то насоветовать разумное... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 6 августа, 2019 Опубликовано 6 августа, 2019 (изменено) · Жалоба Самый быстрый способ могу предложить только такой: SBFX R1,R0,#0,#1 STRH R1,[R2,#0] SBFX R1,R0,#1,#1 STRH R1,[R2,#2] .... SBFX R1,R0,#7,#1 STRH R1,[R2,#14] По два такта на пиксель. Это вполне и при помощи GCC inline asm делается, так что можно обойтись без отдельного модуля на ассемблере. Изменено 6 августа, 2019 пользователем Rst7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 4 минуты назад, jcxz сказал: А зачем такая куча условных выражений? Ведь каждое - это ветвление, а значит особенные тормоза. Я дополню. Если процессорный конвейер равен 6-ти, то каждое ветвление, т.е. вызов или возврат - это 6 тактов ожидания. В этом плане проще сделать 6 команд последовательно, чем одно ветвление. Ну и тут надо смотреть, есть ли команды не "перехода по условию", а "пропуска команды по условию"... Потому как пропуск команды - это только один такт, а не 6... А вот дальше надо смотреть, как именно производится запись в экранную память. Если запись возможно только на обратном ходе луча, то можно посчитать, сколько циклов записи туда влезет. И возможно, что быстрее будет подсинхронизироваться с этим процессом - на прямом ходе луча вычислять, а на обратном быстро, быстро писать в экранную память... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 232 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 13 минут назад, Rst7 сказал: Самый быстрый способ могу предложить только такой: По два такта на пиксель. Это так можно только если действительно можно не записывать старшие 16 бит. Я выше уже писал об этом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 6 августа, 2019 Опубликовано 6 августа, 2019 · Жалоба 29 minutes ago, jcxz said: Это так можно только если действительно можно не записывать старшие 16 бит. Я выше уже писал об этом. Я так думаю, что если сдуру там и сделано 32 бита только, то можно писать не 0 и 0xFFFF, а 0 и 0xFFFFFFFF почти наверняка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
inventor 0 7 августа, 2019 Опубликовано 7 августа, 2019 · Жалоба 13 hours ago, jcxz said: А что такое display_put_pixel() - предлагаете телепатам угадать? Очередная угадайка.... /** * Вывод пикселя на экран с координатами x, y и с заданым цветом */ IDEF void display_put_pixel(u16 x, u16 y, u16 col) { volatile u32 addr; if (x < DISPLAY_WIDTH && y < DISPLAY_HEIGTH) { /* расчитаем координаты точки */ addr = DISPLAY_START_ADDR + (((DISPLAY_HEIGTH - y - 1) * DISPLAY_WIDTH + x) << 2); /* Выведем точку */ *((u32 *) (addr)) = col; // printf("%d, %d; ", x, y); } } IDEF это static inline 13 hours ago, Obam said: Восемь раз display_put_pixel вызывается и каждый раз аргумент вычисляется (DISPLAY_HEIGTH - y): есть гарантия что не 8 раз одно и то же? Из цикла по x - долой... убрал u16 h = DISPLAY_HEIGTH - y; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 232 7 августа, 2019 Опубликовано 7 августа, 2019 · Жалоба 2 часа назад, inventor сказал: if (x < DISPLAY_WIDTH && y < DISPLAY_HEIGTH) { /* расчитаем координаты точки */ addr = DISPLAY_START_ADDR + (((DISPLAY_HEIGTH - y - 1) * DISPLAY_WIDTH + x) << 2); /* Выведем точку */ *((u32 *) (addr)) = col; // printf("%d, %d; ", x, y); } Да уж... Вы действительно сделали всё, чтобы затормозить работу как можно сильнее... 13 часов назад, Rst7 сказал: Я так думаю, что если сдуру там и сделано 32 бита только, то можно писать не 0 и 0xFFFF, а 0 и 0xFFFFFFFF почти наверняка. Глядя на код ТС-а, там можно ожидать чего угодно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться