В настоящее время я работаю над графическим приложением в WPF. По соображениям производительности (и из любопытства) я использую SharpGL для рендеринга графиков, который отлично работает. По крайней мере, на поверхности.
Когда я недавно переключился на использование массива буферов вершин, чтобы минимизировать вызовы отрисовки и поместить больше кода масштабирования в шейдеры, я обнаружил утечку памяти. Я в основном перешел с использования gl.Vertex(px, py, z);
на код, показанный ниже. Это привело к значительному увеличению частоты кадров, но также в приложении внезапно произошла утечка памяти, что можно увидеть на снимке экрана профилирования. Первый скачок происходит при загрузке данных графика, но после этого в основном продолжается рост.
Результаты профилирования
Кто-нибудь может указать мне, где может быть проблема? В основном это соответствует образцу кода из репозитория SharpGL, который, как я ожидал, будет работать нормально. видимый временной диапазон. В будущем, если возможно, это будет перенесено в вершинный шейдер.
Вот код отрисовки (не очень оптимизированный, не очень чистый, но, я думаю, вы поняли):
private void openGLControl1_OpenGLDraw(object sender, SharpGL.WPF.OpenGLRoutedEventArgs args)
{
// Get the OpenGL instance.
var gl = args.OpenGL;
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT | OpenGL.GL_STENCIL_BUFFER_BIT);
// Resample datapoints dynamically if horizontal scale changed
if (_horizontalScale != _prevHorizontalScale || firstRender)
{
ApplyDynamicDownsampling(ActiveSeriesCount, false, false);
_prevHorizontalScale = _horizontalScale;
}
// Rendering process
int z = 0;
double x_min = 0;
double x_max = 1;
double y_min = 0.0;
double y_max = 0.0;
double x_start = _startingPoint;
double x_end = _startingPoint + _horizontalScale;
foreach (string sname in _rawSeries.Keys)
{
// Vertex and color data (flattened)
float[] vertexData = new float[3* _sampledPoints[sname].Count];
float[] colorData = new float[3 * _sampledPoints[sname].Count];
// Only draw enabled series
if (_sampledPoints.ContainsKey(sname) && _rawSeries[sname].Enabled)
{
var col = _rawSeries[sname].Color;
// Flatten datapoints for vertex buffer
float px, py;
for (int i = 0; i < _sampledPoints[sname].Count; i++)
{
// Get point coordinates
px = (float)_sampledPoints[sname][i].X;
py = (float)_sampledPoints[sname][i].Y;
// Get graph limits
x_min = Math.Min(x_min, px);
x_max = Math.Max(x_max, px);
y_min = Math.Min(y_min, py);
y_max = Math.Max(y_max, py);
// Store vertex data
vertexData[3 * i + 0] = px;
vertexData[3 * i + 1] = py;
vertexData[3 * i + 2] = z;
// Store color data
colorData[3 * i + 0] = (float)col.R / 255.0f;
colorData[3 * i + 1] = (float)col.G / 255.0f;
colorData[3 * i + 2] = (float)col.B / 255.0f;
}
// Create a orthogonal projection matrix and map 0...HorizontalScale to the screen
projectionMatrix = glm.ortho(0, (float)_horizontalScale, (float)y_min, (float)y_max);
// Translate the whole graph based on the chosen starting point
modelMatrix = glm.translate(new mat4(1.0f), new vec3(-(float)_startingPoint, 0,0));
// Vertex Array Buffer Variant
// ------------------------------------------
// Create the vertex buffer array object.
vertexBufferArray.Bind(gl);
vertexBufferArray.Create(gl);
vertexBufferArray.Bind(gl);
// Create a vertex buffer for the vertex data.
vertexDataBuffer.Create(gl);
vertexDataBuffer.Bind(gl);
vertexDataBuffer.SetData(gl, attribute_vpos, vertexData, false, 3);
// Now do the same for the colour data.
colourDataBuffer.Create(gl);
colourDataBuffer.Bind(gl);
colourDataBuffer.SetData(gl, attribute_vcol, colorData, false, 3);
// Unbind the vertex buffer array, we've finished specifying data for it.
vertexBufferArray.Unbind(gl);
// Shader-Stuff
shaderProgram.Bind(gl);
shaderProgram.SetUniformMatrix4(gl, "projectionMatrix", projectionMatrix.to_array());
shaderProgram.SetUniformMatrix4(gl, "viewMatrix", viewMatrix.to_array());
shaderProgram.SetUniformMatrix4(gl, "modelMatrix", modelMatrix.to_array());
// Render vertex buffer contents
vertexBufferArray.Bind(gl);
gl.DrawArrays(OpenGL.GL_LINE_STRIP, 0, _sampledPoints[sname].Count);
vertexBufferArray.Unbind(gl);
// Shader-Stuff
shaderProgram.Unbind(gl);
}
}
}