glDrawArrays access violation recording location

I am trying to render a very large point cloud (700 million glDrawArrays

), and in glDrawArrays

the debugger call throws an exception where the access violation is written. I use the same code to render smaller clouds (100M) and everything works fine. I also have enough RAM (32GB) to store my data.

To store the point cloud I use std::vector<Point3D<float>>

where Point3D

template <class T>
union Point3D
{
    T data[3];
        struct{
            T x;
            T y;
            T z;
        };
}

      

Vertex array and buffer initialization:

glBindVertexArray(pxCloudHeader.uiVBA);

glBindBuffer(GL_ARRAY_BUFFER, pxCloudHeader.xVBOs.uiVBO_XYZ);
glBufferData(GL_ARRAY_BUFFER, pxCloudHeader.iPointsCount * sizeof(GLfloat) * 3, &p3DfXYZ->data[0], GL_STREAM_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

glBindVertexArray(0);

      

Call draw:

glBindVertexArray(pxCloudHeader.uiVBA);
glDrawArrays(GL_POINTS, 0, pxCloudHeader.iPointsCount); // here exception is thrown
glBindVertexArray(0);

      

I also checked to see if an OpenGL error was thrown, but I couldn't find any.

+3


source to share


2 answers


I suspect your problem is sizing GLsizeiptr

.

This is the data type used to represent dimensions in OpenGL buffer objects, and is typically 32-bit.

700 million vertices * 4-bytes per-component * 3-components = 8,400,000,000 bytes

      

There is a serious problem trying to allocate that many bytes in GL if they are using 32-bit pointers:

8400000000 & 0xFFFFFFFF = 4,105,032,704 (half as many bytes as you actually need)

      



If sizeof (GLsizeiptr)

your implementation is 4 , then you will have no choice but to split the array. 32-bit GLsizeiptr

allows you to store 4 contiguous GiBs of memory, but you can get around this if you use 3 one-piece arrays instead. Using a vertex shader, you can reconstruct these 3 separate (small enough) arrays, for example:

#version 330

layout (location = 0) in float x; // Vertex Attrib Ptr. 0
layout (location = 1) in float y; // Vertex Attrib Ptr. 1
layout (location = 2) in float z; // Vertex Attrib Ptr. 2

void main (void)
{
  gl_Position = vec4 (x,y,z,1.0);
}

      

The performance will be terrible, but this is one way to approach the problem with minimal effort.


By the way, the amount of system memory here (32 GB) is not the biggest question. You have to think about the amount of VRAM on your GPU because the ideal buffer objects are meant to be stored on the GPU. Any part of the buffer object that is too large to be stored in GPU memory must be carried over the PCIe bus (these days) when it is in use.

0


source


You can paint data in smaller batches. Although there is a predefined upper limit for the buffer size, storing 8 GB of data in a single buffer is a lot . I'm not really surprised that something will explode.

I would probably start by storing roughly one million or at most a few million points in each buffer. Then use a buffer pool with that fixed size, just enough to hold all of your data points.



It might even be useful for you, because it allows you to start sending paint calls before copying all of your data to the buffers. This will give you the best match between CPU and GPU performance.

With the amount of data you are shuffling around, you can also examine glMapBuffer()

/ glUnmapBuffer()

instead glBufferData()

. This usually avoids one copying of data.

0


source







All Articles