Перейти к содержанию
    

Allwinner T113-s3 уделал HiFi4 DSP. Смеяться или плакать?

On 6/27/2022 at 1:44 PM, repstosw said:

А что по адресу 0x7010000 хранится?

судя по DTS диапазон адресов 0x07010000 - 0x07010240 относится к одному из блоков управления тактированием

 

https://github.com/Tina-Linux/tina-t113-linux-5.4/blob/150c69d4f2b0886db269cc7883f007e2cdcd839c/arch/arm/boot/dts/sun8iw20p1.dtsi#L419

 

Quote

        r_ccu: r_ccu@7010000 {
            compatible = "allwinner,sun8iw20-r-ccu";
            reg = <0x0 0x07010000 0x0 0x240>;
            clocks = <&dcxo24M>, <&rtc_ccu CLK_OSC32K>, <&rtc_ccu CLK_IOSC>,
                 <&ccu CLK_PLL_PERIPH0>;
            clock-names = "hosc", "losc", "iosc", "pll-periph0";
            #clock-cells = <1>;
            #reset-cells = <1>;
        };

драйвер тут

 

https://github.com/Tina-Linux/tina-t113-linux-5.4/blob/150c69d4f2b0886db269cc7883f007e2cdcd839c/drivers/clk/sunxi-ng/ccu-sun8iw20-r.c#L131

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Успешно запустил G2D. :sun_bespectacled:

 

Проверил на отрисовке прямоугольников и BitBlt.  Над прозрачностью и порядком отрисовки пришлось поломать голову, но сделал.

 

На картинке - Blt с учётом альфы.  Цветовое представление: ARGB.  Прикрутил декодер PNG-файлов. (по краям изображение хорошо сглаживается).

 

 

G2D.jpg.f70ea6f908f7b86937dd6df445de1cf1.jpg

 

Есть некоторые моменты:

 

1) GD2 не может одновременно использовать Mixer и Rotator.  Либо смешиваем, либо поворачиваем

 

2) Отсутствует отсечение: если изображение выходит за пределы рабочей области - повисает

 

3) Критичны размеры.  Например, прямоугольник размером 1x1 пиксель он не выведет.  Минимальный - 2x1 пиксел

 

 

 

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 28.06.2022 в 14:10, repstosw сказал:

Например, прямоугольник размером 1x1 пиксель он не выведет.

Больше интересует производительность, сколько по времени рисует закрашенный квадрат во весь экран НЕОНом и этим g2d?

В 28.06.2022 в 14:10, repstosw сказал:

если изображение выходит за пределы рабочей области - повисает

Эт как-то не радует, конечно.. Виснет ускоритель или вся система?

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/28/2022 at 9:23 PM, mantech said:

Больше интересует производительность, сколько по времени рисует закрашенный квадрат во весь экран НЕОНом и этим g2d?

Скоро об этом напишу.   Какой клок ставить ускорителю?

 

По поводу производительности  - даже если будет одинаково или чуть-медленее - не смертельно.  Главное, что параллельно.  CPU может делать другие вещи, в то время когда G2D рисует. Заложить буферизацию.

 

Ну например - время отрисовки CPU 10 мкс, а время отрисовки G2D - 15 мкс,  время процессора на выполнение остального кода - 10 мкс.

Здесь CPU шустрее рисует в 1,5 раза.  Но один он всё сделает за:  10 + 10 = 20 мкс

А вместе с GPU на всё уйдёт  MAX(15, 10) =15 мкс

В этом примере выигрыш в производительности 20/15 = 1,333  (на 30% что неплохо)

 

 

 

On 6/28/2022 at 9:23 PM, mantech said:

Эт как-то не радует, конечно.. Виснет ускоритель или вся система?

 Скорее всего ускоритель.  У меня пока программный поллинг (опрос занятости ускорителя перед отрисовкой следующего элемента).   Уточню позже.

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 28.06.2022 в 14:36, repstosw сказал:

даже если будет одинаково или чуть-медленее - не смертельно.  Главное, что параллельно.  CPU может делать другие вещи, в то время когда G2D рисует. Заложить буферизацию.

В моем случае это не имеет значения, т.к. надо нарисовать кучу квадратов, затем текст и только потом переключится на другое дело - один фиг ждать надо завершения, но использование подобных корок накладывает ограничения на переносимость, НЕОН-то во всех армах есть, а вот g2d только в Т113, в v3s, например его нет, так что перенести не получится, и если скорость примерно одинаковая, то смысла большого не вижу,ИМХО...

 

ЗЫ. Кстати, хотел спросить, как вы делаете синхронизацию рисования картинок или прямоугольников с обновлением экрана. Допустим, частота 50Гц, и вам надо нарисовать картинку, ждете прерывания окончания очередного обновления экрана и начинаете рисовать? А если оно уже началось, то надо снова 1\50 сек ждать? Долго ведь получается...

Или это только для крупных фигур, а мелкие можно рисовать в любое время?

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/28/2022 at 10:25 PM, mantech said:

ЗЫ. Кстати, хотел спросить, как вы делаете синхронизацию рисования картинок или прямоугольников с обновлением экрана. Допустим, частота 50Гц, и вам надо нарисовать картинку, ждете прерывания окончания очередного обновления экрана и начинаете рисовать? А если оно уже началось, то надо снова 1\50 сек ждать? Долго ведь получается...

Или это только для крупных фигур, а мелкие можно рисовать в любое время?

 

Я рисую в заднем буфере. Когда всё отрисовано - скидываю весь буфер на экран. В этом случае синхронизация с экраном нужна только 1 раз - когда  скидываю буфер целиком на экран.  Синхронизация самая простая - опрос регистра LCD_GINT0_REG и сброс ему бита:

 

void VSync(void)
{
 LCD_GINT0_REG&=~(1<<15);         //clear LCD_VB_INT_FLAG
 while(!(LCD_GINT0_REG&(1<<15))); //wait  LCD_VB_INT_FLAG
}

 

Перед этим, нужно разрешить VB:

 

 LCD_GINT0_REG|=(1<<31); //Enable the Vertical Blank interrupt

 

Можно также через прерывание TCON .  Оба способа работают.   Но так как на прерывании у меня обновление DMA для звука, то использую опрос VSync() перед отправкой данных на экран.

Всё очень плавно и гладко движется.  Причем даже сбрасывать с кеша не нужно.  Экранная память буферизована, но не кеширована, также бит 12 (TEX) установлен.  Память заднего буфера - обычная:  кеширована и буферизована.   Это режим с наибольшей производительностью, когда задний буфер надо и читать и писать процессором. А экранная память только читается TCON/DE,  и пересылка NEON'ом (запись)  1 раз.

 

У C6745 есть PRU, там можно этот VSync заставить ждать сопроцессором, основной CPU идёт дальше...

 

Возвращаясь к G2D: он работает на любом участке DDR:  для каждой картинки можно назначить свой адрес источника, или сделать один общий атлас картинок в памяти, а потом вырезать нужную и показывать. G2D это всё может! :yes:

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я попытался сделать:

В dbuff ставится младший бит и ждем пока снимется.
Но судя по иногда промаргивающему изображению, это не то...

    write32((uintptr_t) & glb->dbuff, 0x01uL);    // 1: register value be ready for update (self-cleaning bit)
    while ((read32((uintptr_t) & glb->dbuff) & 0x01uL) != 0)
        ;
// Allwinner_DE2.0_Spec_V1.0
// 5.10.3.4 Blender
// GLB
struct de_glb_t {
    uint32_t ctl;        /** Offset 0x000 Global control register */
    uint32_t status;    /** Offset 0x004 Global status register */
    uint32_t dbuff;        /** Offset 0x008 Global double buffer control register */
    uint32_t size;        /** Offset 0x00C Global size register */
};

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 28.06.2022 в 16:52, repstosw сказал:

Когда всё отрисовано - скидываю весь буфер на экран.

В смысле? Копируете весь теневой буфер в экранный или перекидываете адреса DE с активной экранной области на теневую во время обратного хода?

ЗЫ. Хотя, если теневая область закэширована, то походу только копирование...

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/28/2022 at 5:59 PM, GenaSPB said:

В dbuff ставится младший бит и ждем пока снимется.

Это как раз надеюсь на синхронизацию с vsync

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

оставил своё и добавил ваше - помогло. Но вообще где-то должен быть способ по настоящему синхронизироваться, не в ручную ловить момент.

Т.е. как в STM32 LTDC и Renessas VD5: выставил в регистр новый адрес страницы, дождался когда дисплей на него перейдет - и все, поехал заполнять старый буфер.

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/29/2022 at 12:59 AM, GenaSPB said:

Я попытался сделать:

В dbuff ставится младший бит и ждем пока снимется.
Но судя по иногда промаргивающему изображению, это не то...

 

Рисовалки типа G2D и DE отставить... Тут только TCON, без вариантов. Обновлять изображение нужно в те моменты, когда TCON не сканирует память. Иначе артефакты на экране будут визуально ощутимы.

 

О вкусах не спорят: Double Buffering vs. Page Flipping : https://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html

 

Для моих целей (игры) более подходит двойная буферизация, чем переключение страниц. Потому что не всегда надо перерисовывать всё полностью.

 

Перед переключением страницы тоже нужно ждать VSync:

 

void DE_SwitchBuffer(u8 channel,u8 buffer) //channel = 0,1,2 ; buffer = 0,1
{
 int j;
 switch(channel)
 {
  case 0: //CH0
   for(j=0;j<3;j++)writel(buffer?CH0_BUFFER1:CH0_BUFFER0,&de_vi_regs0->cfg[0].top_laddr[j]); //CH0 LAYMB_LADD
  break;
  case 1: //CH1
   for(j=0;j<3;j++)writel(buffer?CH1_BUFFER1:CH1_BUFFER0,&de_vi_regs1->cfg[0].top_laddr[j]); //CH1 LAYMB_LADD
  break;
  case 2: //CH2
   writel(buffer?CH2_BUFFER1:CH2_BUFFER0,&de_ui_regs->cfg[0].top_laddr);                     //CH2 LAYMB_LADD
  break;
 }
}

void DE_ComposerApply(void)
{
 writel(1,&de_glb_regs->dbuff); //composer enable
}

void main(void)
{
  //...
  u8 page=0;
  
  while(1)
  {
     //...
     VSync();
    
     DE_SwitchBuffer(0,page);
     DE_ComposerApply();
    
     page^=1;
    
     Draw_Scene(page);
     //...
  }
  //...
}

 

On 6/29/2022 at 3:08 AM, GenaSPB said:

оставил своё и добавил ваше - помогло. Но вообще где-то должен быть способ по настоящему синхронизироваться, не в ручную ловить момент.

 

Разрешить прерывание от TCON. В обработчике переключать страницу.

 

Чтобы вручную не ловить момент - можно задействовать второе ядро у T113-s3  или его HiFi-DSP.  И сделать отложенную отрисовку на экран: дать команду сопроцессору, а тот будет ждать VSync, а main CPU пойдёт дальше.   Я так делал на C6745, у него есть пара сопроцессоров, как раз один из них рисовал на экран и ждал VSync.

 

Ну или чисто софт-вариант: потоки (threads).   Создать поток и в нём проверять.:biggrin:

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/28/2022 at 10:25 PM, mantech said:

Допустим, частота 50Гц, и вам надо нарисовать картинку, ждете прерывания окончания очередного обновления экрана и начинаете рисовать? А если оно уже началось, то надо снова 1\50 сек ждать? Долго ведь получается...

 

Не долго.  50 Гц это 20 мс. За эти 20 мс процессор может горы свернуть. Не уверен, что оставшаяся часть вашей программы займёт больше времени.   Долго может быть только первая итерация цикла. Затем система входит в синхрон и на эти 20 мс успевает ещё не только выполнить код, но и дождаться следующего VSync.

 

Но если вдруг 20 мс не хватит, тогда да, очередной VSync будет пропущен и придётся ждать следующего.  В этом случае уже будет не 50 FPS, а в 2 раза меньше.

А если программа требует более 40 мс, то уже 2 VSync будут пропущены.  FPS тут просядет уже в 3 раза...  

Это в любом учебнике по игрострою расписано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 29.06.2022 в 03:54, repstosw сказал:

Но если вдруг 20 мс не хватит, тогда да, очередной VSync будет пропущен и придётся ждать следующего.

Решил взять золотую середину, т.к. по пред. опыту отрисовки gif-анимации, те объекты, которые занимают четверть экрана и меньше, рисовать без синхронизации, все, что больше, полноэкранки и пр - ждать, получается визуально не заметно...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/29/2022 at 4:27 PM, mantech said:

Решил взять золотую середину, т.к. по пред. опыту отрисовки gif-анимации, те объекты, которые занимают четверть экрана и меньше, рисовать без синхронизации, все, что больше, полноэкранки и пр - ждать, получается визуально не заметно...

 

Вы валите всё прямо на экранную память??? :shok: Оно ж мерцать будет, когда одни картинки поверх других рисуются циклически...

 ---

 

Копирование из памяти в память (тесты G2D и NEON).

 

Частота ядра CPU: 1008 MHz. Настройки DDR памяти штатные(xfel). Все прерывания запрещены.

 

Параметры картинки: 800x480 пикселов, цветовое пространство ARGB8888.
Размер картинки: ровно 1500 кБ.

---

 

NEON:

 

Параметры региона памяти источника: кеширован(C=1) и буферизован(B=1).

 

100 копирований NEON занимает:

 

(параметры региона памяти приёмника: C=0, B=1, TEX=1) => 156.667 мс : 638 FPS - самый быстрй режим у NEON
(параметры региона памяти приёмника: C=0, B=1, TEX=0) => 181.682 мс : 550 FPS
(параметры региона памяти приёмника: C=0, B=0, TEX=0) => 754.668 мс : 133 FPS

 

Выводы: если чтение CPU из буфера приёмника не планируется, то для максимально быстрого копирования в него, нужно включать буферизацию(B=1) и (TEX=1). Кеширование отключить(C=0).

---

 

G2D:

 

Тактируется от PLL_VIDEO0(4x): 297 MHz*4 = 1188 MHz

 

100 копирований G2D (BitBLT) занимает:

 

(делитель частоты тактирования регистра G2D_CLK_REG: / 3 ) => 116.191 мс : 861 FPS - быстрее, чем NEON
(делитель частоты тактирования регистра G2D_CLK_REG: / 6 ) => 124.128 мс : 806 FPS
(делитель частоты тактирования регистра G2D_CLK_REG: /12 ) => 210.649 мс : 475 FPS

 

Выводы: производительность G2D слабо зависит от частоты тактирования регистра G2D_CLK_REG. Очевидно, тут бОльшую роль играет частота DDR: ведь данные в ней.

---

 

Выводы и замечания общего плана:

 

G2D победил NEON(1008 MHz) - выигрыш в 1.35 (35%). С учётом параллельности общая производительность программ будет ещё выше.

 

Если делитель G2D_CLK_REG выставить меньше 3 (при частоте PLLVIDEO0(4x) = 1188 MHz), то G2D не будет правильно работать.

Чтение памяти TCON(отображение на экране) не снижает скорость работы NEON или G2D. Очевидно, помогает буферизация или хорошо продуманный арбитраж шины.

---

 

//...
 u32 t;

 while(1)
 {
  t=AVS_CNT0_REG; //разрешающая способность таймера 24/4 = 6 MHz

  for(int i=0;i<100;i++)
  {
   G2D_Blt(DST_BUF,SRC_BUF,800*480*4); //NEON_Copy(DST_BUF,SRC_BUF,800*480*4);
  }
 
  t=AVS_CNT0_REG-t;

  UART0_putn(t);
 }
//...

 

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверил после подсказки... вертикальные линии или прямоугольники в один пиксель g2d  сейчас не заполняет. Вместо этого рисует горизонтальную линию такого же размера (на вид) и не выставляется прерывание по готовности.

Горизонтальные линии нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...