render implement thread, wrap GL commands into tasks

This commit is contained in:
2019-07-06 22:25:07 +02:00
parent db27334ce5
commit 0012e2ce9b
18 changed files with 1252 additions and 904 deletions

View File

@@ -1,6 +1,7 @@
#include "pch.h"
#include "log.h"
#include "shape.h"
#include "app.h"
bool Shape::create_buffers(GLushort * idx, GLvoid * vertices, int isize, int vsize)
{
@@ -20,79 +21,99 @@ bool Shape::create_buffers_imp(GLvoid* idx, GLvoid* vertices, int isize, int vsi
{
use_idx = true;
destroy();
glGenBuffers(2, buffers);
if (!(buffers[0] && buffers[1]))
return false;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, isize, idx, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vsize, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
#if USE_VBO
glGenVertexArrays(2, arrays);
if (!(arrays[0] && arrays[1]))
return false;
for (int i = 0; i < 2; i++)
bool ret = false;
App::I.render_task([&]
{
glBindVertexArray(arrays[i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
destroy();
glGenBuffers(2, buffers);
if (!(buffers[0] && buffers[1]))
{
ret = false;
return;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, isize, idx, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
}
glBindVertexArray(0);
glBufferData(GL_ARRAY_BUFFER, vsize, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
#if USE_VBO
glGenVertexArrays(2, arrays);
if (!(arrays[0] && arrays[1]))
{
ret = false;
return;
}
for (int i = 0; i < 2; i++)
{
glBindVertexArray(arrays[i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
}
glBindVertexArray(0);
#endif
return true;
});
return ret;
}
bool Shape::create_buffers(GLvoid* vertices, int vsize)
{
use_idx = false;
destroy();
bool ret = false;
App::I.render_task([&]
{
destroy();
glGenBuffers(1, buffers);
if (!buffers[0])
{
ret = false;
return;
}
if (vsize)
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vsize, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glGenBuffers(1, buffers);
if (!buffers[0])
return false;
if (vsize)
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vsize, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
#if USE_VBO
glGenVertexArrays(2, arrays);
if (!(arrays[0] && arrays[1]))
return false;
for (int i = 0; i < 2; i++)
{
glBindVertexArray(arrays[i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
}
glBindVertexArray(0);
glGenVertexArrays(2, arrays);
if (!(arrays[0] && arrays[1]))
{
ret = false;
return;
}
for (int i = 0; i < 2; i++)
{
glBindVertexArray(arrays[i]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs2));
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, nor));
}
glBindVertexArray(0);
#endif
return true;
});
return ret;
}
void Shape::draw_fill() const
{
@@ -103,31 +124,34 @@ void Shape::draw_fill() const
type = GL_POINTS;
if (count[0] == 2)
type = GL_LINES;
#if USE_VBO
glBindVertexArray(arrays[0]);
if (use_idx)
glDrawElements(type, count[0], index_type, ioff[0]);
else
glDrawArrays(type, 0, count[0]);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
if (use_idx)
App::I.render_task([=]
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glDrawElements(type, count[0], GL_UNSIGNED_SHORT, ioff[0]);
}
else
glDrawArrays(type, 0, count[0]);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#if USE_VBO
glBindVertexArray(arrays[0]);
if (use_idx)
glDrawElements(type, count[0], index_type, ioff[0]);
else
glDrawArrays(type, 0, count[0]);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
if (use_idx)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glDrawElements(type, count[0], GL_UNSIGNED_SHORT, ioff[0]);
}
else
glDrawArrays(type, 0, count[0]);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif // USE_VBO
});
}
void Shape::draw_stroke() const
{
@@ -136,32 +160,61 @@ void Shape::draw_stroke() const
GLenum type = GL_LINES;
if (count[1] == 1)
type = GL_POINTS;
#if USE_VBO
glBindVertexArray(arrays[1]);
if (use_idx)
glDrawElements(type, count[1], index_type, ioff[1]);
else
glDrawArrays(type, 0, count[1]);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
if (use_idx)
App::I.render_task([=]
{
#if USE_VBO
glBindVertexArray(arrays[1]);
if (use_idx)
glDrawElements(type, count[1], index_type, ioff[1]);
else
glDrawArrays(type, 0, count[1]);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glDrawElements(type, count[1], GL_UNSIGNED_SHORT, ioff[1]);
}
else
glDrawArrays(type, 0, count[1]);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
if (use_idx)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glDrawElements(type, count[1], GL_UNSIGNED_SHORT, ioff[1]);
}
else
glDrawArrays(type, 0, count[1]);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#endif // USE_VBO
});
}
void Shape::destroy()
{
App::I.render_task_async([b1=buffers[0],b2=buffers[1],a1=arrays[0],a2=arrays[1]]
{
if (b1 || b2)
{
glDeleteBuffers(1, &b1);
glDeleteBuffers(1, &b2);
}
#if USE_VBO
if (a1 || a2)
{
glDeleteVertexArrays(1, &a1);
glDeleteVertexArrays(1, &a2);
}
#endif // USE_VBO
});
buffers[0] = buffers[1] = 0;
arrays[0] = arrays[1] = 0;
}
Shape::~Shape()
{
destroy();
}
bool RectShape::create(float w, float h)
@@ -437,21 +490,24 @@ void Plane::update_vertices(const glm::vec4* data, const glm::vec2* uvs, const g
vertices[i].pos.z = q;
}
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
static GLushort idx[6 + 8]{
0, 1, 2,
0, 2, 3,
0, 1,
1, 2,
2, 3,
3, 0,
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idx), idx, GL_STATIC_DRAW);
App::I.render_task([this]
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
static GLushort idx[6 + 8]{
0, 1, 2,
0, 2, 3,
0, 1,
1, 2,
2, 3,
3, 0,
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idx), idx, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
});
}
void Circle::create_impl(float radius, int div, GLushort* idx, vertex_t* vertices)
{
@@ -704,18 +760,24 @@ void Sphere::create_impl(int rings, int sectors, float radius,
}
void LineSegment::update_vertices(const glm::vec4 data[2])
{
static vertex_t vertices[2];
vertices[0] = { data[0], { 0, 0 } }; // A
vertices[1] = { data[1], { 0, 1 } }; // B
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
App::I.render_task([&]
{
static vertex_t vertices[2];
vertices[0] = { data[0], { 0, 0 } }; // A
vertices[1] = { data[1], { 0, 1 } }; // B
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
});
}
void DynamicShape::update_vertices(vertex_t* vertices, int vcount)
{
count[0] = vcount;
count[1] = vcount;
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_t) * vcount, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
App::I.render_task([&]
{
count[0] = vcount;
count[1] = vcount;
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_t) * vcount, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
});
}