AnsweredAssumed Answered

glMultiDrawArrays bug!

Question asked by dextirias on Sep 1, 2014
Latest reply on Dec 13, 2014 by cippyboy

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

Outcomes