1 Reply Latest reply on Dec 13, 2014 8:49 AM by cippyboy

    glMultiDrawArrays bug!

    dextirias

      This method "glMultiDrawArrays" isn't working properly with the AMD drivers (the same problem occurs with every AMD driver regardless of the operating system 32-64 bit, not including Linux), compared to intel, nvidia and even on my old laptop with SiS MIrage 3+ graphics where this method is working properly.

       

      The AMD graphics cards on which I have tested this method are: HD5670, IGP HD3000 and IGP X1200.

       

      The image on the left show the way it should look compared to the right that presents the bug.

      Untitled2.jpgUntitled.jpg

       

      Here is a example code to this bug!

       

      /**********************************
      *
      *    controls:
      *    F1 - exit
      *    F2 - 1K circles
      *    F3 - 10k
      *    F4 - 100k
      *    F5 - rotate
      *    F6 - switch between  glMultiDrawArrays or glVertex3f
      *    F12 - Toggle between fullscreen
      *
      **************************************/
      
      #include <stdio.h>
      #include <time.h>
      #include <math.h>
      #include "GL/glew.h"
      #include "GL/freeglut.h"
      
      enum _size_k{C1k = 1000, C10k = 10000, C100k = 100000};
      
      static bool Full_screen = false, isRotation = false, isMulti = true;
      static int persp = 178, newPersp = 178;
      static float WindowSizeW = 800;
      static float WindowSizeH = 600;
      static int my_case = C1k;
      static int fps = 0;
      static clock_t t = 0, _t;
      
      struct C4UB_V3F {
          unsigned char RGBA[4];
          float xyz[3];
          };
      
      static GLvoid *GraphInterleavedArray;
      static GLint     first_ptr[100000];
      static GLsizei count[100000];
      
      GLvoid Display(void){
        
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
          if(isMulti)
              glMultiDrawArrays(GL_LINE_LOOP, first_ptr, count,  my_case);
          else{
              C4UB_V3F *cv = (C4UB_V3F *) GraphInterleavedArray;
              for(int i = 0 ; i < my_case ; i++){
                  glPushMatrix();
                      glBegin(GL_LINE_LOOP);
                    
                          glColor4ub(cv[first_ptr[i]].RGBA[0],
                                     cv[first_ptr[i]].RGBA[1],
                                     cv[first_ptr[i]].RGBA[2],
                                     cv[first_ptr[i]].RGBA[3]);
                                  
                          for(int j = 0 ; j < count[i] ; j++)
                              glVertex3f(cv[first_ptr[i]+j].xyz[0],
                                         cv[first_ptr[i]+j].xyz[1],
                                         cv[first_ptr[i]+j].xyz[2]);
                      glEnd();
                  glPopMatrix();
                  }
              }
        
            glutSwapBuffers();
          }
        
      GLvoid IdleFunc(void){
        
          _t = clock();
          if(_t - t >= 1000){
            
              char text[36] = {0};
              sprintf(text, "%dk fps:%d Multi:%s", my_case/1000, fps, (isMulti ? "On" : "Off"));
              glutSetWindowTitle(text);
            
              t = _t;
              fps = 0;
              }
          ++fps;
        
          if(isRotation)glRotatef(0.45f, 0.f, 0.f, 0.25f);
        
          glutPostRedisplay();
          }
      
      GLvoid processSpecialKeys(int key, int x, int y) {
      
          switch(key) {
              case GLUT_KEY_F11: break;
              case GLUT_KEY_F12:  
                 if(Full_screen ? Full_screen = false : Full_screen = true)glutFullScreenToggle();
                 else glutLeaveFullScreen();    
                break;
      
              case GLUT_KEY_UP:                                 break;
              case GLUT_KEY_DOWN:                             break;
              case GLUT_KEY_F1:         glutLeaveMainLoop();      break;          
              case GLUT_KEY_F2:         my_case = C1k;             break;      
              case GLUT_KEY_F3:         my_case = C10k;         break;      
              case GLUT_KEY_F4:         my_case = C100k;          break;          
              case GLUT_KEY_F5: isRotation ? isRotation = false : isRotation = true; break;    
              case GLUT_KEY_F6: isMulti ? isMulti = false : isMulti = true; break;
                    
              default: break;
              }
      }  
      
      GLvoid ZoomInOut(int x, int y){
      
          if(WindowSizeH == 0)
              WindowSizeH = 1;
      
          float ratio = 1.0* WindowSizeW / WindowSizeH;
      
          // Reset the coordinate system before modifying
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
      
          // Set the viewport to be the entire window
          glViewport(0, 0, WindowSizeW, WindowSizeH);
      
          // Set the correct perspective.
          gluPerspective(persp,ratio,1,1000);
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
          gluLookAt(0.0f, 0.0f, 5.0f,
                    0.0f, 0.0f, -1.0f,
                    0.0f, 1.0f, 0.0f);
          }
      
      GLvoid mouseWheel(int button, int dir, int x, int y){
        
          if (dir < 0 && persp < 178){
                 newPersp+=2;
              }
          else if(dir > 0 && persp > 4){
                 newPersp-=2;
              }
          if(persp != newPersp){
              persp = newPersp;
              ZoomInOut(x, y);
             }
          }
      
      GLvoid Reshape(int w, int h) {
        
          WindowSizeW = w;
          WindowSizeH = h;
        
          // Prevent a divide by zero, when window is too short
          // (you cant make a window of zero width).
          if(h == 0)
              h = 1;
      
          float ratio = 1.0* w / h;
      
          // Reset the coordinate system before modifying
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
      
          // Set the viewport to be the entire window
          //SMenu->AutoViewPort();
          glViewport(0, 0, w, h);
      
          // Set the correct perspective.
          gluPerspective(persp,ratio,1,1000);
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
          gluLookAt(0.0f , 0.0f, 5.0f,
                    0.0f, 0.0f, -1.0f,
                    0.0f, 1.0f, 0.0f);
      }
      
      
      void SpiralOFCircles(void){
        
        
          size_t s100k = 100000*36*sizeof(C4UB_V3F);
        
          GraphInterleavedArray = (GLvoid *) malloc(s100k);
          C4UB_V3F *g100k = (C4UB_V3F *)GraphInterleavedArray;
        
          float v_angle = 2.0 * M_PI/36;
          float Angle = 2.0 * M_PI/360;
          int g = 0, var = 59;
        
          float x = 0.0f, y = 0.0f;
        
          for(int i = 0 ; i < 100000 ; i++){
              if(i != 0){
                
                  x = (float)(i/var * cos(g*Angle));
                  y = (float)(i/var * sin(g*Angle));
                
                  for(int j = 0 ; j < 36 ; j++){
                      g100k[i*36+j].RGBA[0]     = 0x33;
                      g100k[i*36+j].RGBA[1]      = 0x99;
                      g100k[i*36+j].RGBA[2]      = 0xFF;
                      g100k[i*36+j].RGBA[3]      = 0xFF;
                      g100k[i*36+j].xyz[0]      = x + 0.2 * cos(j*v_angle);
                        g100k[i*36+j].xyz[1]      = y + 0.2 * sin(j*v_angle);
                        g100k[i*36+j].xyz[2]      = 0.0f;
                      
                      }
                  if(g >= 360) g = 0;
                  ++g;
                  }
              else{
                  for(int j = 0 ; j < 36 ; j++){
                      g100k[i*36+j].RGBA[0]     = 0x33;
                      g100k[i*36+j].RGBA[1]      = 0x99;
                      g100k[i*36+j].RGBA[2]      = 0xFF;
                      g100k[i*36+j].RGBA[3]      = 0xFF;
                      g100k[i*36+j].xyz[0]      = x + 0.2 * cos(j*v_angle);
                        g100k[i*36+j].xyz[1]      = y + 0.2 * sin(j*v_angle);
                        g100k[i*36+j].xyz[2]      = 0.0f;
                      
                      }
                  }
              count[i] = 36;
              first_ptr[i] = i*36;
              }
          }
      
      
      GLint InitGraph(int argc, char *argv[]){
        
          GLint window;
            
          glutInit(&argc, argv);
          glutInitWindowSize(800 , 600);
          glutInitWindowPosition(0,100);
          glutInitDisplayMode(GLUT_DOUBLE | GLUT_MULTISAMPLE | GLUT_RGBA);
        
          window = glutCreateWindow("OGL Sample");
            
          //Init GLEW
          GLenum err = glewInit();
           if (GLEW_OK != err)
             /* Problem: glewInit failed, something is seriously wrong. */
             fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
           else fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
        
          glEnable (GL_LINE_SMOOTH);
          glEnable(GL_POINT_SMOOTH);
          glEnable (GL_BLEND);
          glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
          glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
          glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
          glLineWidth(2.0);
          glPointSize(10.0);
        
          glutMouseWheelFunc(mouseWheel);
          glutSpecialFunc(processSpecialKeys);
        
          glutReshapeFunc(Reshape);
        
          glutDisplayFunc(Display);
          glutIdleFunc(IdleFunc);
        
          glInterleavedArrays(GL_C4UB_V3F, 0, GraphInterleavedArray);
            
          glutMainLoop();
        
          glutExit();
          }
      
      int main(int argc, char *argv[]){
        
          SpiralOFCircles();
          InitGraph(argc, argv);
        
          return 0;
          }
      
      

       

      Message was edited by: Todor Ivanov