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

Делаю расчёты в формате floating point.  

К примеру - делю одно на другое.

В асм-листинге вижу такое:

$C$RL64:   ; CALL OCCURS {__c6xabi_divf} {0}  ; [] |147| 
;** --------------------------------------------------------------------------*

           CALLP   .S2     __c6xabi_divf,B3  ; [B_Sb674] |147| 

Как это безобразие называется???

Аппаратная поддержка floating point?

C6745 вообще поддерживает операции с плавающей точкой или нет?   Я ожидал инлайнинга иструкций на ассемблере, а не вызов функций с черт-пойми каким содержимым.

 

Как итог: программа тормозит, и скорее всего там идёт целочисленная эмуляция плавучки.

Спецы, подскажите, как заставить генериться код с ассемблерными инструкциями плавучки?

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


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

4 минуты назад, __inline__ сказал:

Как это безобразие называется???

Это безобразие Вы сами и устроили. Везде, где можно обойтись без деления, нужно обходиться без него.

4 минуты назад, __inline__ сказал:

C6745 вообще поддерживает операции с плавающей точкой или нет?

Конечно. Но кто Вам сказал, что он имеет аппаратное деление? Да даже если бы и имел, то даже аппаратное деление не перестаёт быть делением.

Вы вроде бы писали что раньше работали с другими DSP? Тогда странно не знать об этом.

4 минуты назад, __inline__ сказал:

Как итог: программа тормозит, и скорее всего там идёт целочисленная эмуляция плавучки.

Тормозит не из-за мнимой эмуляции, а из-за наличия инструкций вызова CALL. Их не может быть в быстрых аппаратных циклах. Я не зря вам свои функции приводил.

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


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

9 minutes ago, jcxz said:

Тормозит не из-за мнимой эмуляции, а из-за наличия инструкций вызова CALL. Их не может быть в быстрых аппаратных циклах. Я не зря вам свои функции приводил.

Это мне понятно.  Непонятно, как заставить инлайниться во floating-point такой кусок кода:

float A=0.4F;
float B=0.223424F;
float C;

void main(void)
{
 C=A/B;
}

Это простое деление, и оно должно инлайниться в инструкции ,  а не через CALL  вызываться.

 

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


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

Неужели это деление тоже через интринсики надо писать?   Очень неудобно.  В том же Keil + STM32 с их поддержкой VFPv4 плавучка инлайнится напрямую без применения интринсиков..

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


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

14 минут назад, __inline__ сказал:

Это простое деление, и оно должно инлайниться в инструкции ,  а не через CALL  вызываться.

Ну так A и B - переменные же. Соответственно их деление компилятор не может заменить умножением. А команды деления (аппаратной) в этом ядре видимо нет (уже точно не помню, но скорей всего так). Поэтому вызывается библиотечная функция.

2 минуты назад, __inline__ сказал:

Неужели это деление тоже через интринсики надо писать?   Очень неудобно.  В том же Keil + STM32 с их поддержкой VFPv4 плавучка инлайнится напрямую без применения интринсиков..

"В том же" есть аппаратная команда деления.

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


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

1. Если делитель - константа, то замените деление умножением на обратное (хотя по идее компилятор сам должен это делать).

2. Если делитель - переменная, но деление делается в цикле с одним и тем же значением делителя, то вычислите однократно 1/B, а потом умножайте. Я даже для Cortex-ов так делаю, когда важна скорость.

Также насколько помню - в этом DSP-ядре есть быстрая инструкция вычисления обратного значения от числа (1/x) - используйте её интринсинк для нахождения обратного.

 

PS: При написании быстрого кода для этого ядра, нужно придерживаться правила чтобы в циклах нижнего уровня не было вызовов функций. Даже библиотечных. Иначе не будет использоваться SPLOOP.

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


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

Да. Хочешь умножения - дели на константу, а не на переменную.

А вообще-то аппаратное деление  это довольно экзотическое явление.  В цпос обычно реализована команда малоразрядного вычисления 1/y. Затем через ньютона-рафсона достигается требуемая точность и результат умножается на x. Использовать либские функции в масовом делении не надо. Надо написать собственную инлайн без глупостей типо проверок деления на 0 и пр наны.  Вычисление квадратного корня реализовано  примерно так же. Только примитив 1/sqrt(y).

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

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


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

Спасибо огромное!  Да, заменил деление везде на  умножение на интринсик _rcpsp() - тормоза исчезли, всё идёт очень лихо!

Было 67 делений в программе. Часть из них сидели в цикле отрисовки линий.

 

 

 

Попутно спрошу, есть ли возможность поменять местами значения переменных, а то приходится писать что-то вроде такого:

if(p0y>p1y)
 {
  templ=p0y;
  p0y=p1y;
  p1y=templ;

 

Весь код (начальный, без оптимизации) - привожу ниже. Рисуем текстуры....  На STM32H743 этот код просто летает.

Spoiler

#define MaxX H
#define MaxY W

#define P1 12 /* грань */
#define P2 32 /* длина */

#define D 3.0F /* дистанция */

#if TUNNEL_SIMPLE

#define SPEED 0.5F
#define TEXTURE_SPEED 5.0F

#else

#define SPEED 0.75F
#define TEXTURE_SPEED 20.0F

#endif

#define PI 3.14159265358979323846F

#define TRUNC(x) ((s32)(x))

float Angle=0.0F;

struct TVertex
{
 float X,Y,Z;
};

struct TVertex Vertex[P1+1][P2];

u16 (*Texture)[MaxU][MaxV]=(u16 (*)[MaxU][MaxV])TUNNEL;

s32       y;
float     x1,x2,z1,z2,u1,u2,v1,v2;
float     dz,du,dv;

void ClearCQ(void)
{
 for(register u32 y=((MaxX*(MaxY/4))+(MaxX/4))<<1;y<((MaxX*((3*MaxY)/4))+(MaxX/4))<<1;y+=(MaxX<<1))memset((void*)(SwitchBuffer[0]+y),0,MaxX);
}

inline void Line(void)
{
 if(y<0)return;

 register s32 a,b,c;

 a=TRUNC(x1);
 b=TRUNC(x2);

 if((a<0)&&(b<0))return;
 if(((a>=MaxX))&&(b>=MaxX))return;

 if(a>b)
 {
  c=a;
  a=b;
  b=c;
  c=1;
 }
 else c=0;

 if(a<0)a=0;
 if(b>=MaxX)b=MaxX-1;

 if(a==b)return;

 register float z,u,v;
 register float xx1,xx2;

 if(c==0)if(a==0)
 {
  z=z1-x1*dz;
  u=u1-x1*du;
  v=v1-x1*dv;
 }
 else
 {
  xx1=x1-(float)a;
  z=z1-xx1*dz;
  u=u1-xx1*du;
  v=v1-xx1*dv;
 }
 else if(a==0)
 {
  z=z2-x2*dz;
  u=u2-x2*du;
  v=v2-x2*dv;
 }
 else
 {
  xx2=x2-(float)a;
  z=z2-xx2*dz;
  u=u2-xx2*du;
  v=v2-xx2*dv;
 }

 register u16 *vb=(u16*)(SwitchBuffer[0]+(((y*MaxX)+a)<<1));

 b-=(a-1);

 while(b--)
 {
  *vb++=(*Texture)[TRUNC(v/z)&(MaxV-1)][TRUNC(u/z)&(MaxU-1)];
  z=z+dz;
  u=u+du;
  v=v+dv;
 }
}

void Triangle(float k0x,float k0y,float k0z,float k0u,float k0v,float k1x,float k1y,float k1z,float k1u,float k1v,float k2x,float k2y,float k2z,float k2u, float k2v)
{
 register float     ddx,ddy;
 register float     temps;
 register s32       templ;
 register s32       p0y,p1y,p2y;
 register float     p0x,p1x,p2x;
 register float     p0z,p1z,p2z;
 register float     p0u,p1u,p2u;
 register float     p0v,p1v,p2v;
 register float     dx1,dz1,du1,dv1;
 register float     dx2,dz2,du2,dv2;
 register float     dx3,dz3,du3,dv3;
 
 p0z=D/k0z;
 p0x=(MaxX/2.0F)+k0x*p0z;
 p0y=TRUNC((MaxY/2.0F)-(k0y*p0z));
 p0u=k0u*p0z;
 p0v=k0v*p0z;
 p1z=D/k1z;
 p1x=(MaxX/2.0F)+k1x*p1z;
 p1y=TRUNC((MaxY/2.0F)-(k1y*p1z));
 p1u=k1u*p1z;
 p1v=k1v*p1z;
 p2z=D/k2z;
 p2x=(MaxX/2.0F)+k2x*p2z;
 p2y=TRUNC((MaxY/2.0F)-(k2y*p2z));
 p2u=k2u*p2z;
 p2v=k2v*p2z;

 if(p0y>p1y)
 {
  templ=p0y;
  p0y=p1y;
  p1y=templ;

  temps=p0x;
  p0x=p1x;
  p1x=temps;

  temps=p0z;
  p0z=p1z;
  p1z=temps;

  temps=p0u;
  p0u=p1u;
  p1u=temps;

  temps=p0v;
  p0v=p1v;
  p1v=temps;
 };

 if(p0y>p2y)
 {
  templ=p0y;
  p0y=p2y;
  p2y=templ;

  temps=p0x;
  p0x=p2x;
  p2x=temps;

  temps=p0z;
  p0z=p2z;
  p2z=temps;

  temps=p0u;
  p0u=p2u;
  p2u=temps;

  temps=p0v;
  p0v=p2v;
  p2v=temps;
 };

 if(p1y>p2y)
 {
  templ=p1y;
  p1y=p2y;
  p2y=templ;

  temps=p1x;
  p1x=p2x;
  p2x=temps;

  temps=p1z;
  p1z=p2z;
  p2z=temps;

  temps=p1u;
  p1u=p2u;
  p2u=temps;

  temps=p1v;
  p1v=p2v;
  p2v=temps;
 };

 if(p0y==p1y)
 {
  ddy=1.0F/(p2y-p0y);
  dx1=(p2x-p0x)*ddy;
  dz1=(p2z-p0z)*ddy;
  du1=(p2u-p0u)*ddy;
  dv1=(p2v-p0v)*ddy;
  dx2=p1x-p0x;
  ddy=1.0F/(p2y-p1y);
  dx3=(p2x-p1x)*ddy;
  dz3=(p2z-p1z)*ddy;
  du3=(p2u-p1u)*ddy;
  dv3=(p2v-p1v)*ddy;
  ddx=1.0F/(dx3-dx1);
  dz=(dz3-dz1)*ddx;
  du=(du3-du1)*ddx;
  dv=(dv3-dv1)*ddx;
  if(dx1>dx2)
  {
   x1=p1x;
   x2=p0x;
   z1=p1z;
   z2=p0z;
   u1=p1u;
   u2=p0u;
   v1=p1v;
   v2=p0v;
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx3;
    x2=x2+dx1;
    z1=z1+dz3;
    z2=z2+dz1;
    u1=u1+du3;
    u2=u2+du1;
    v1=v1+dv3;
    v2=v2+dv1;
   };
  }
  else
  {
   x1=p0x;
   x2=p1x;
   z1=p0z;
   z2=p1z;
   u1=p0u;
   u2=p1u;
   v1=p0v;
   v2=p1v;
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx1;
    x2=x2+dx3;
    z1=z1+dz1;
    z2=z2+dz3;
    u1=u1+du1;
    u2=u2+du3;
    v1=v1+dv1;
    v2=v2+dv3;
   };
  };
 }
 else if(p1y==p2y)
 {
  ddy=1.0F/(p2y-p0y);
  dx1=(p2x-p0x)*ddy;
  dz1=(p2z-p0z)*ddy;
  du1=(p2u-p0u)*ddy;
  dv1=(p2v-p0v)*ddy;
  ddy=1.0F/(p1y-p0y);
  dx2=(p1x-p0x)*ddy;
  dz2=(p1z-p0z)*ddy;
  du2=(p1u-p0u)*ddy;
  dv2=(p1v-p0v)*ddy;
  ddx=1.0F/(dx2-dx1);
  dz=(dz2-dz1)*ddx;
  du=(du2-du1)*ddx;
  dv=(dv2-dv1)*ddx;
  x1=p0x;
  x2=p0x;
  z1=p0z;
  z2=p0z;
  u1=p0u;
  u2=p0u;
  v1=p0v;
  v2=p0v;
  if(dx1>dx2)for(y=p0y;y<=p1y;y++)
  {
   if(y>MaxY-1)return;
   Line();
   x1=x1+dx2;
   x2=x2+dx1;
   z1=z1+dz2;
   z2=z2+dz1;
   u1=u1+du2;
   u2=u2+du1;
   v1=v1+dv2;
   v2=v2+dv1;
  }
  else for(y=p0y;y<=p1y;y++)
  {
   if(y>MaxY-1)return;
   Line();
   x1=x1+dx1;
   x2=x2+dx2;
   z1=z1+dz1;
   z2=z2+dz2;
   u1=u1+du1;
   u2=u2+du2;
   v1=v1+dv1;
   v2=v2+dv2;
  };
 }
 else
 {
  ddy=1.0F/(p2y-p0y);
  dx1=(p2x-p0x)*ddy;
  dz1=(p2z-p0z)*ddy;
  du1=(p2u-p0u)*ddy;
  dv1=(p2v-p0v)*ddy;
  ddy=1.0F/(p1y-p0y);
  dx2=(p1x-p0x)*ddy;
  dz2=(p1z-p0z)*ddy;
  du2=(p1u-p0u)*ddy;
  dv2=(p1v-p0v)*ddy;
  ddy=1.0F/(p2y-p1y);
  dx3=(p2x-p1x)*ddy;
  dz3=(p2z-p1z)*ddy;
  du3=(p2u-p1u)*ddy;
  dv3=(p2v-p1v)*ddy;
  ddx=1.0F/(dx2-dx1);
  dz=(dz2-dz1)*ddx;
  du=(du2-du1)*ddx;
  dv=(dv2-dv1)*ddx;
  x1=p0x;
  x2=p0x;
  z1=p0z;
  z2=p0z;
  u1=p0u;
  u2=p0u;
  v1=p0v;
  v2=p0v;
  if(dx1>dx2)
  {
   for(y=p0y;y<p1y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx2;
    x2=x2+dx1;
    z1=z1+dz2;
    z2=z2+dz1;
    u1=u1+du2;
    u2=u2+du1;
    v1=v1+dv2;
    v2=v2+dv1;
   };
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx3;
    x2=x2+dx1;
    z1=z1+dz3;
    z2=z2+dz1;
    u1=u1+du3;
    u2=u2+du1;
    v1=v1+dv3;
    v2=v2+dv1;
   };
  }
  else
  {
   for(y=p0y;y<p1y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx1;
    x2=x2+dx2;
    z1=z1+dz1;
    z2=z2+dz2;
    u1=u1+du1;
    u2=u2+du2;
    v1=v1+dv1;
    v2=v2+dv2;
   };
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx1;
    x2=x2+dx3;
    z1=z1+dz1;
    z2=z2+dz3;
    u1=u1+du1;
    u2=u2+du3;
    v1=v1+dv1;
    v2=v2+dv3;
   };
  };
 };
};

void Tunnel(void)
{
 s32 i,j;

 Angle+=SPEED;

 for(i=0;i<=P1;i++)for(j=0;j<P2;j++)
 {
  Vertex[i][j].X=(MaxX/2.0F)*((3.0F-(((float)j)/P1))*cosf(((2.0F*PI/P1)*((float)i)))+2.0F*sinf((Angle+(2.0F*((float)j)))/29.0F)+cosf((Angle+(2.0F*((float)j)))/13.0F)-2.0F*sinf(Angle/29.0F)-cosf(Angle/13.0F));
  Vertex[i][j].Y=(MaxY/2.0F)*((3.0F-(((float)j)/P1))*sinf(((2.0F*PI/P1)*((float)i)))+2.0F*cosf((Angle+(2.0F*((float)j)))/33.0F)+sinf((Angle+(2.0F*((float)j)))/17.0F)-2.0F*cosf(Angle/33.0F)-sinf(Angle/17.0F));
  Vertex[i][j].Z=((float)j)+1.0F;
 }

 for(j=P2-2;j>=0;j--)
 {
  float J1=MaxV-((MaxV*((float) j   ))/P2)-(Angle*TEXTURE_SPEED);
  float J2=MaxV-((MaxV*((float)(j+1)))/P2)-(Angle*TEXTURE_SPEED);

  for(i=0;i<P1;i++)
  {
   float I1=MaxU-((MaxU*((float)(i-3+P1)))/P1);
   float I2=MaxU-((MaxU*((float)(i-2+P1)))/P1);

   Triangle(
            Vertex[i  ][j  ].X,Vertex[i  ][j  ].Y,Vertex[i  ][j  ].Z,I1,J1, //0
            Vertex[i+1][j  ].X,Vertex[i+1][j  ].Y,Vertex[i+1][j  ].Z,I2,J1, //1
            Vertex[i+1][j+1].X,Vertex[i+1][j+1].Y,Vertex[i+1][j+1].Z,I2,J2  //2
           );
   Triangle(
            Vertex[i  ][j  ].X,Vertex[i  ][j  ].Y,Vertex[i  ][j  ].Z,I1,J1, //0
            Vertex[i+1][j+1].X,Vertex[i+1][j+1].Y,Vertex[i+1][j+1].Z,I2,J2, //2
            Vertex[i  ][j+1].X,Vertex[i  ][j+1].Y,Vertex[i  ][j+1].Z,I1,J2  //3
           );
  }
 }
}

int main(void)
{
 SCB_EnableICache();
 SCB_EnableDCache();

 HAL_Init();

 SystemClock_Config();

 MX_GPIO_Init();
 MX_FMC_Init();
 MX_DMA_Init();

 LCD_Reset();

 LCD_Init();

 LCD_Position(0,0,W-1,H-1);

 
 Loop:

 LCD_Transfer();

 ClearCQ();

 Tunnel();
 
 goto Loop;
}

 

 

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

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


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

15 минут назад, __inline__ сказал:

Попутно спрошу, есть ли возможность поменять местами значения переменных, а то приходится писать что-то вроде такого:

А что не устраивает в таком коде? Если напрягает громоздкость текста - так оберните в макрос. А компилиться это будет оптимально: чем более простые конструкции используете - тем лучше работает оптимизатор.

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


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

33 минуты назад, __inline__ сказал:

Спасибо огромное!  Да, заменил деление везде на  умножение на интринсик _rcpsp() - тормоза исчезли, всё идёт очень лихо!

Было 67 делений в программе. Часть из них сидели в цикле отрисовки линий.

 

 

 

Попутно спрошу, есть ли возможность поменять местами значения переменных, а то приходится писать что-то вроде такого:


if(p0y>p1y)
 {
  templ=p0y;
  p0y=p1y;
  p1y=templ;

 

Весь код (начальный, без оптимизации) - привожу ниже. Рисуем текстуры....  На STM32H743 этот код просто летает.

  Показать контент


#define MaxX H
#define MaxY W

#define P1 12 /* грань */
#define P2 32 /* длина */

#define D 3.0F /* дистанция */

#if TUNNEL_SIMPLE

#define SPEED 0.5F
#define TEXTURE_SPEED 5.0F

#else

#define SPEED 0.75F
#define TEXTURE_SPEED 20.0F

#endif

#define PI 3.14159265358979323846F

#define TRUNC(x) ((s32)(x))

float Angle=0.0F;

struct TVertex
{
 float X,Y,Z;
};

struct TVertex Vertex[P1+1][P2];

u16 (*Texture)[MaxU][MaxV]=(u16 (*)[MaxU][MaxV])TUNNEL;

s32       y;
float     x1,x2,z1,z2,u1,u2,v1,v2;
float     dz,du,dv;

void ClearCQ(void)
{
 for(register u32 y=((MaxX*(MaxY/4))+(MaxX/4))<<1;y<((MaxX*((3*MaxY)/4))+(MaxX/4))<<1;y+=(MaxX<<1))memset((void*)(SwitchBuffer[0]+y),0,MaxX);
}

inline void Line(void)
{
 if(y<0)return;

 register s32 a,b,c;

 a=TRUNC(x1);
 b=TRUNC(x2);

 if((a<0)&&(b<0))return;
 if(((a>=MaxX))&&(b>=MaxX))return;

 if(a>b)
 {
  c=a;
  a=b;
  b=c;
  c=1;
 }
 else c=0;

 if(a<0)a=0;
 if(b>=MaxX)b=MaxX-1;

 if(a==b)return;

 register float z,u,v;
 register float xx1,xx2;

 if(c==0)if(a==0)
 {
  z=z1-x1*dz;
  u=u1-x1*du;
  v=v1-x1*dv;
 }
 else
 {
  xx1=x1-(float)a;
  z=z1-xx1*dz;
  u=u1-xx1*du;
  v=v1-xx1*dv;
 }
 else if(a==0)
 {
  z=z2-x2*dz;
  u=u2-x2*du;
  v=v2-x2*dv;
 }
 else
 {
  xx2=x2-(float)a;
  z=z2-xx2*dz;
  u=u2-xx2*du;
  v=v2-xx2*dv;
 }

 register u16 *vb=(u16*)(SwitchBuffer[0]+(((y*MaxX)+a)<<1));

 b-=(a-1);

 while(b--)
 {
  *vb++=(*Texture)[TRUNC(v/z)&(MaxV-1)][TRUNC(u/z)&(MaxU-1)];
  z=z+dz;
  u=u+du;
  v=v+dv;
 }
}

void Triangle(float k0x,float k0y,float k0z,float k0u,float k0v,float k1x,float k1y,float k1z,float k1u,float k1v,float k2x,float k2y,float k2z,float k2u, float k2v)
{
 register float     ddx,ddy;
 register float     temps;
 register s32       templ;
 register s32       p0y,p1y,p2y;
 register float     p0x,p1x,p2x;
 register float     p0z,p1z,p2z;
 register float     p0u,p1u,p2u;
 register float     p0v,p1v,p2v;
 register float     dx1,dz1,du1,dv1;
 register float     dx2,dz2,du2,dv2;
 register float     dx3,dz3,du3,dv3;
 
 p0z=D/k0z;
 p0x=(MaxX/2.0F)+k0x*p0z;
 p0y=TRUNC((MaxY/2.0F)-(k0y*p0z));
 p0u=k0u*p0z;
 p0v=k0v*p0z;
 p1z=D/k1z;
 p1x=(MaxX/2.0F)+k1x*p1z;
 p1y=TRUNC((MaxY/2.0F)-(k1y*p1z));
 p1u=k1u*p1z;
 p1v=k1v*p1z;
 p2z=D/k2z;
 p2x=(MaxX/2.0F)+k2x*p2z;
 p2y=TRUNC((MaxY/2.0F)-(k2y*p2z));
 p2u=k2u*p2z;
 p2v=k2v*p2z;

 if(p0y>p1y)
 {
  templ=p0y;
  p0y=p1y;
  p1y=templ;

  temps=p0x;
  p0x=p1x;
  p1x=temps;

  temps=p0z;
  p0z=p1z;
  p1z=temps;

  temps=p0u;
  p0u=p1u;
  p1u=temps;

  temps=p0v;
  p0v=p1v;
  p1v=temps;
 };

 if(p0y>p2y)
 {
  templ=p0y;
  p0y=p2y;
  p2y=templ;

  temps=p0x;
  p0x=p2x;
  p2x=temps;

  temps=p0z;
  p0z=p2z;
  p2z=temps;

  temps=p0u;
  p0u=p2u;
  p2u=temps;

  temps=p0v;
  p0v=p2v;
  p2v=temps;
 };

 if(p1y>p2y)
 {
  templ=p1y;
  p1y=p2y;
  p2y=templ;

  temps=p1x;
  p1x=p2x;
  p2x=temps;

  temps=p1z;
  p1z=p2z;
  p2z=temps;

  temps=p1u;
  p1u=p2u;
  p2u=temps;

  temps=p1v;
  p1v=p2v;
  p2v=temps;
 };

 if(p0y==p1y)
 {
  ddy=1.0F/(p2y-p0y);
  dx1=(p2x-p0x)*ddy;
  dz1=(p2z-p0z)*ddy;
  du1=(p2u-p0u)*ddy;
  dv1=(p2v-p0v)*ddy;
  dx2=p1x-p0x;
  ddy=1.0F/(p2y-p1y);
  dx3=(p2x-p1x)*ddy;
  dz3=(p2z-p1z)*ddy;
  du3=(p2u-p1u)*ddy;
  dv3=(p2v-p1v)*ddy;
  ddx=1.0F/(dx3-dx1);
  dz=(dz3-dz1)*ddx;
  du=(du3-du1)*ddx;
  dv=(dv3-dv1)*ddx;
  if(dx1>dx2)
  {
   x1=p1x;
   x2=p0x;
   z1=p1z;
   z2=p0z;
   u1=p1u;
   u2=p0u;
   v1=p1v;
   v2=p0v;
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx3;
    x2=x2+dx1;
    z1=z1+dz3;
    z2=z2+dz1;
    u1=u1+du3;
    u2=u2+du1;
    v1=v1+dv3;
    v2=v2+dv1;
   };
  }
  else
  {
   x1=p0x;
   x2=p1x;
   z1=p0z;
   z2=p1z;
   u1=p0u;
   u2=p1u;
   v1=p0v;
   v2=p1v;
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx1;
    x2=x2+dx3;
    z1=z1+dz1;
    z2=z2+dz3;
    u1=u1+du1;
    u2=u2+du3;
    v1=v1+dv1;
    v2=v2+dv3;
   };
  };
 }
 else if(p1y==p2y)
 {
  ddy=1.0F/(p2y-p0y);
  dx1=(p2x-p0x)*ddy;
  dz1=(p2z-p0z)*ddy;
  du1=(p2u-p0u)*ddy;
  dv1=(p2v-p0v)*ddy;
  ddy=1.0F/(p1y-p0y);
  dx2=(p1x-p0x)*ddy;
  dz2=(p1z-p0z)*ddy;
  du2=(p1u-p0u)*ddy;
  dv2=(p1v-p0v)*ddy;
  ddx=1.0F/(dx2-dx1);
  dz=(dz2-dz1)*ddx;
  du=(du2-du1)*ddx;
  dv=(dv2-dv1)*ddx;
  x1=p0x;
  x2=p0x;
  z1=p0z;
  z2=p0z;
  u1=p0u;
  u2=p0u;
  v1=p0v;
  v2=p0v;
  if(dx1>dx2)for(y=p0y;y<=p1y;y++)
  {
   if(y>MaxY-1)return;
   Line();
   x1=x1+dx2;
   x2=x2+dx1;
   z1=z1+dz2;
   z2=z2+dz1;
   u1=u1+du2;
   u2=u2+du1;
   v1=v1+dv2;
   v2=v2+dv1;
  }
  else for(y=p0y;y<=p1y;y++)
  {
   if(y>MaxY-1)return;
   Line();
   x1=x1+dx1;
   x2=x2+dx2;
   z1=z1+dz1;
   z2=z2+dz2;
   u1=u1+du1;
   u2=u2+du2;
   v1=v1+dv1;
   v2=v2+dv2;
  };
 }
 else
 {
  ddy=1.0F/(p2y-p0y);
  dx1=(p2x-p0x)*ddy;
  dz1=(p2z-p0z)*ddy;
  du1=(p2u-p0u)*ddy;
  dv1=(p2v-p0v)*ddy;
  ddy=1.0F/(p1y-p0y);
  dx2=(p1x-p0x)*ddy;
  dz2=(p1z-p0z)*ddy;
  du2=(p1u-p0u)*ddy;
  dv2=(p1v-p0v)*ddy;
  ddy=1.0F/(p2y-p1y);
  dx3=(p2x-p1x)*ddy;
  dz3=(p2z-p1z)*ddy;
  du3=(p2u-p1u)*ddy;
  dv3=(p2v-p1v)*ddy;
  ddx=1.0F/(dx2-dx1);
  dz=(dz2-dz1)*ddx;
  du=(du2-du1)*ddx;
  dv=(dv2-dv1)*ddx;
  x1=p0x;
  x2=p0x;
  z1=p0z;
  z2=p0z;
  u1=p0u;
  u2=p0u;
  v1=p0v;
  v2=p0v;
  if(dx1>dx2)
  {
   for(y=p0y;y<p1y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx2;
    x2=x2+dx1;
    z1=z1+dz2;
    z2=z2+dz1;
    u1=u1+du2;
    u2=u2+du1;
    v1=v1+dv2;
    v2=v2+dv1;
   };
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx3;
    x2=x2+dx1;
    z1=z1+dz3;
    z2=z2+dz1;
    u1=u1+du3;
    u2=u2+du1;
    v1=v1+dv3;
    v2=v2+dv1;
   };
  }
  else
  {
   for(y=p0y;y<p1y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx1;
    x2=x2+dx2;
    z1=z1+dz1;
    z2=z2+dz2;
    u1=u1+du1;
    u2=u2+du2;
    v1=v1+dv1;
    v2=v2+dv2;
   };
   for(y=p1y;y<=p2y;y++)
   {
    if(y>MaxY-1)return;
    Line();
    x1=x1+dx1;
    x2=x2+dx3;
    z1=z1+dz1;
    z2=z2+dz3;
    u1=u1+du1;
    u2=u2+du3;
    v1=v1+dv1;
    v2=v2+dv3;
   };
  };
 };
};

void Tunnel(void)
{
 s32 i,j;

 Angle+=SPEED;

 for(i=0;i<=P1;i++)for(j=0;j<P2;j++)
 {
  Vertex[i][j].X=(MaxX/2.0F)*((3.0F-(((float)j)/P1))*cosf(((2.0F*PI/P1)*((float)i)))+2.0F*sinf((Angle+(2.0F*((float)j)))/29.0F)+cosf((Angle+(2.0F*((float)j)))/13.0F)-2.0F*sinf(Angle/29.0F)-cosf(Angle/13.0F));
  Vertex[i][j].Y=(MaxY/2.0F)*((3.0F-(((float)j)/P1))*sinf(((2.0F*PI/P1)*((float)i)))+2.0F*cosf((Angle+(2.0F*((float)j)))/33.0F)+sinf((Angle+(2.0F*((float)j)))/17.0F)-2.0F*cosf(Angle/33.0F)-sinf(Angle/17.0F));
  Vertex[i][j].Z=((float)j)+1.0F;
 }

 for(j=P2-2;j>=0;j--)
 {
  float J1=MaxV-((MaxV*((float) j   ))/P2)-(Angle*TEXTURE_SPEED);
  float J2=MaxV-((MaxV*((float)(j+1)))/P2)-(Angle*TEXTURE_SPEED);

  for(i=0;i<P1;i++)
  {
   float I1=MaxU-((MaxU*((float)(i-3+P1)))/P1);
   float I2=MaxU-((MaxU*((float)(i-2+P1)))/P1);

   Triangle(
            Vertex[i  ][j  ].X,Vertex[i  ][j  ].Y,Vertex[i  ][j  ].Z,I1,J1, //0
            Vertex[i+1][j  ].X,Vertex[i+1][j  ].Y,Vertex[i+1][j  ].Z,I2,J1, //1
            Vertex[i+1][j+1].X,Vertex[i+1][j+1].Y,Vertex[i+1][j+1].Z,I2,J2  //2
           );
   Triangle(
            Vertex[i  ][j  ].X,Vertex[i  ][j  ].Y,Vertex[i  ][j  ].Z,I1,J1, //0
            Vertex[i+1][j+1].X,Vertex[i+1][j+1].Y,Vertex[i+1][j+1].Z,I2,J2, //2
            Vertex[i  ][j+1].X,Vertex[i  ][j+1].Y,Vertex[i  ][j+1].Z,I1,J2  //3
           );
  }
 }
}

int main(void)
{
 SCB_EnableICache();
 SCB_EnableDCache();

 HAL_Init();

 SystemClock_Config();

 MX_GPIO_Init();
 MX_FMC_Init();
 MX_DMA_Init();

 LCD_Reset();

 LCD_Init();

 LCD_Position(0,0,W-1,H-1);

 
 Loop:

 LCD_Transfer();

 ClearCQ();

 Tunnel();
 
 goto Loop;
}

 

 

32-х битные нет. На ти ифы в цикле летают очень плохо. Впрочем, на ад тоже не особо. Конвейеры.

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


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

Глянул немного ваш код. Есть маленькое замечание - в Line():

if(y<0)return;
if((a<0)&&(b<0))return;
if(((a>=MaxX))&&(b>=MaxX))return;

лучше, имхо, записать как:

if ((a & b | y) < 0) return;
if ((a - MaxX | b - MaxX) >= 0) return;

а может даже:

if ((~(a - MaxX | b - MaxX) | a & b | y) < 0) return;

так как для DSP: чем меньше переходов в коде - тем быстрее.

Хотя конечно вес этого фрагмента во времени выполнения функции Line() и очень невелик.

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


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

OK, спасибо!

Попутно новая проблема вылезла:

В цикле отрисовки линии :

while(b--)
 {
  FLOAT rz=_rcpsp(z);
  *vb++=(*Texture)[TRUNC(v*rz)&(MaxV-1)][TRUNC(u*rz)&(MaxU-1)];
  z=z+dz;
  u=u+du;
  v=v+dv;
 }

Со временем текстура деградирует - становится дырявой.

В то время когда прежний код, который медлительный из-за делений:

while(b--)
 {
  *vb++=(*Texture)[TRUNC(v/z)&(MaxV-1)][TRUNC(u/z)&(MaxU-1)];
  z=z+dz;
  u=u+du;
  v=v+dv;
 }

работает без деградации текстуры.

Выходит что умножение на обратную величину приводит к потери точности,  так как текстурные координаты постепенно "сползают" и картинка со временем становится дырявой.

Что можно предпринять в этом случае?

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


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

6 минут назад, __inline__ сказал:

OK, спасибо!

Попутно новая проблема вылезла:

В цикле отрисовки линии :


while(b--)
 {
  FLOAT rz=_rcpsp(z);
  *vb++=(*Texture)[TRUNC(v*rz)&(MaxV-1)][TRUNC(u*rz)&(MaxU-1)];
  z=z+dz;
  u=u+du;
  v=v+dv;
 }

Со временем текстура деградирует - становится дырявой.

В то время когда прежний код, который медлительный из-за делений:


while(b--)
 {
  *vb++=(*Texture)[TRUNC(v/z)&(MaxV-1)][TRUNC(u/z)&(MaxU-1)];
  z=z+dz;
  u=u+du;
  v=v+dv;
 }

работает без деградации текстуры.

Выходит что умножение на обратную величину приводит к потери точности,  так как текстурные координаты постепенно "сползают" и картинка со временем становится дырявой.

Что можно предпринять в этом случае?

Нет. rcpsp получает только 8 верных бит. Ошибка накапливается и давай до свидания. Нужно вычислять как минимум 16 бит. Или больше. Т е будет 2-3 итерации ньютона-рафсона.

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


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

24 минуты назад, __inline__ сказал:

Выходит что умножение на обратную величину приводит к потери точности,  так как текстурные координаты постепенно "сползают" и картинка со временем становится дырявой.

Как оно может "сползать" если и в том и в другом случае у Вас z=z+dz, а rz - временная, вычисляемая в каждой итерации из z. Т.е. - ошибки её вычисления нигде не накапливаются.

Видимо проблема где-то в другом месте....

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


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

1 час назад, jcxz сказал:

Как оно может "сползать" если и в том и в другом случае у Вас z=z+dz, а rz - временная, вычисляемая в каждой итерации из z. Т.е. - ошибки её вычисления нигде не накапливаются.

Видимо проблема где-то в другом месте....

Не знаю. Разница только в точности результата деления. Ищите.

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


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

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

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

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

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

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

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

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

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

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