mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
Merge pull request #545 from tophyr/pr/improve-render-perf
Improve Renderer Performance
This commit is contained in:
commit
2db85ca6ec
@ -108,16 +108,21 @@ struct Renderer {
|
|||||||
shader_.setUniform1i("u_texture_enable", texture_enable_);
|
shader_.setUniform1i("u_texture_enable", texture_enable_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVertexData(size_t offset, size_t count, PosColorUV2Vertex const* vertices) {
|
template <typename VertexIter,
|
||||||
shader_.setVertexData(offset, count, vertices);
|
typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<VertexIter>::value_type, PosColorUV2Vertex>>>
|
||||||
|
size_t addVertexData(VertexIter begin, VertexIter end) {
|
||||||
|
return shader_.addVertexData(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVertexData(size_t offset, size_t count, PosColorUVVertex const* vertices) {
|
struct PosColorUVVertex_tag {};
|
||||||
|
template <typename VertexIter,
|
||||||
|
typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<VertexIter>::value_type, PosColorUVVertex>>>
|
||||||
|
size_t addVertexData(VertexIter begin, VertexIter end, PosColorUVVertex_tag = {}) {
|
||||||
std::array<PosColorUV2Vertex, MAX_POINTS_IN_POLY> converted;
|
std::array<PosColorUV2Vertex, MAX_POINTS_IN_POLY> converted;
|
||||||
std::transform(vertices, vertices + count, converted.begin(), [](auto const& vtx) {
|
std::transform(begin, end, converted.begin(), [](auto const& vtx) {
|
||||||
return PosColorUV2Vertex{vtx.pos, vtx.color, vtx.uv, {}};
|
return PosColorUV2Vertex{vtx.pos, vtx.color, vtx.uv, {}};
|
||||||
});
|
});
|
||||||
setVertexData(offset, count, converted.data());
|
return shader_.addVertexData(converted.cbegin(), converted.cend());
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFogEnabled(bool enabled) {
|
void setFogEnabled(bool enabled) {
|
||||||
@ -1281,8 +1286,6 @@ void gpu_BindTexture(int handle, int map_type, int slot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gpu_RenderPolygon(PosColorUVVertex *vData, uint32_t nv) {
|
void gpu_RenderPolygon(PosColorUVVertex *vData, uint32_t nv) {
|
||||||
gRenderer->setVertexData(0, nv, vData);
|
|
||||||
|
|
||||||
if (gpu_state.cur_texture_quality == 0) {
|
if (gpu_state.cur_texture_quality == 0) {
|
||||||
// force disable textures
|
// force disable textures
|
||||||
gRenderer->setTextureEnabled(0, false);
|
gRenderer->setTextureEnabled(0, false);
|
||||||
@ -1291,7 +1294,7 @@ void gpu_RenderPolygon(PosColorUVVertex *vData, uint32_t nv) {
|
|||||||
gRenderer->setTextureEnabled(1, false);
|
gRenderer->setTextureEnabled(1, false);
|
||||||
|
|
||||||
// draw the data in the arrays
|
// draw the data in the arrays
|
||||||
dglDrawArrays(GL_TRIANGLE_FAN, 0, nv);
|
dglDrawArrays(GL_TRIANGLE_FAN, gRenderer->addVertexData(vData, vData + nv), nv);
|
||||||
|
|
||||||
if (gpu_state.cur_texture_quality == 0) {
|
if (gpu_state.cur_texture_quality == 0) {
|
||||||
// re-enable textures
|
// re-enable textures
|
||||||
@ -1304,9 +1307,8 @@ void gpu_RenderPolygon(PosColorUVVertex *vData, uint32_t nv) {
|
|||||||
|
|
||||||
void gpu_RenderPolygonUV2(PosColorUV2Vertex *vData, uint32_t nv) {
|
void gpu_RenderPolygonUV2(PosColorUV2Vertex *vData, uint32_t nv) {
|
||||||
gRenderer->setTextureEnabled(1, true);
|
gRenderer->setTextureEnabled(1, true);
|
||||||
gRenderer->setVertexData(0, nv, vData);
|
|
||||||
|
|
||||||
dglDrawArrays(GL_TRIANGLE_FAN, 0, nv);
|
dglDrawArrays(GL_TRIANGLE_FAN, gRenderer->addVertexData(vData, vData + nv), nv);
|
||||||
OpenGL_polys_drawn++;
|
OpenGL_polys_drawn++;
|
||||||
OpenGL_verts_processed += nv;
|
OpenGL_verts_processed += nv;
|
||||||
|
|
||||||
@ -1547,8 +1549,7 @@ void rend_SetPixel(ddgr_color color, int x, int y) {
|
|||||||
{},
|
{},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
gRenderer->setVertexData(0, 1, &vtx);
|
dglDrawArrays(GL_POINTS, gRenderer->addVertexData(&vtx, &vtx + 1), 1);
|
||||||
dglDrawArrays(GL_POINTS, 0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a pixel on the display
|
// Sets a pixel on the display
|
||||||
@ -1594,8 +1595,7 @@ void rend_DrawLine(int x1, int y1, int x2, int y2) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
gRenderer->setVertexData(0, vertices.size(), vertices.data());
|
dglDrawArrays(GL_LINES, gRenderer->addVertexData(vertices.begin(), vertices.end()), vertices.size());
|
||||||
dglDrawArrays(GL_LINES, 0, vertices.size());
|
|
||||||
|
|
||||||
rend_SetAlphaType(atype);
|
rend_SetAlphaType(atype);
|
||||||
rend_SetLighting(ltype);
|
rend_SetLighting(ltype);
|
||||||
@ -1675,8 +1675,7 @@ void rend_DrawSpecialLine(g3Point *p0, g3Point *p1) {
|
|||||||
{}};
|
{}};
|
||||||
});
|
});
|
||||||
|
|
||||||
gRenderer->setVertexData(0, vertices.size(), vertices.data());
|
dglDrawArrays(GL_LINES, gRenderer->addVertexData(vertices.begin(), vertices.end()), vertices.size());
|
||||||
dglDrawArrays(GL_LINES, 0, vertices.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a screenshot of the current frame and puts it into the handle passed
|
// Takes a screenshot of the current frame and puts it into the handle passed
|
||||||
|
@ -54,15 +54,16 @@ template <typename V>
|
|||||||
struct VertexBuffer {
|
struct VertexBuffer {
|
||||||
VertexBuffer(GLuint program,
|
VertexBuffer(GLuint program,
|
||||||
std::vector<VertexAttrib<V>> attribs,
|
std::vector<VertexAttrib<V>> attribs,
|
||||||
size_t vertex_count,
|
size_t vertexCount,
|
||||||
GLenum bufferType,
|
GLenum bufferType,
|
||||||
V const* initialData = nullptr)
|
V const* initialData = nullptr)
|
||||||
: vao_{outval(dglGenVertexArrays)},
|
: vao_{outval(dglGenVertexArrays)},
|
||||||
vbo_{outval(dglGenBuffers)} {
|
vbo_{outval(dglGenBuffers)} {
|
||||||
dglBindVertexArray(vao_);
|
dglBindVertexArray(vao_);
|
||||||
dglBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
|
||||||
|
bind();
|
||||||
dglBufferData(GL_ARRAY_BUFFER,
|
dglBufferData(GL_ARRAY_BUFFER,
|
||||||
vertex_count * sizeof(PosColorUV2Vertex),
|
vertexCount * sizeof(V),
|
||||||
initialData,
|
initialData,
|
||||||
bufferType);
|
bufferType);
|
||||||
|
|
||||||
@ -78,11 +79,16 @@ struct VertexBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateData(size_t vtx_offset, size_t vtx_count, V const* vertices) const {
|
void UpdateData(size_t vtx_offset, size_t vtx_count, V const* vertices) {
|
||||||
dglBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
bind();
|
||||||
dglBufferSubData(GL_ARRAY_BUFFER, vtx_offset * sizeof(V), vtx_count * sizeof(V), vertices);
|
dglBufferSubData(GL_ARRAY_BUFFER, vtx_offset * sizeof(V), vtx_count * sizeof(V), vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void bind() {
|
||||||
|
dglBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void DeleteBuffer(GLuint id) {
|
static void DeleteBuffer(GLuint id) {
|
||||||
dglDeleteBuffers(1, &id);
|
dglDeleteBuffers(1, &id);
|
||||||
@ -101,6 +107,41 @@ private:
|
|||||||
MoveOnlyHolder<GLuint, DeleteBuffer> vbo_;
|
MoveOnlyHolder<GLuint, DeleteBuffer> vbo_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#Buffer_update
|
||||||
|
template <typename V>
|
||||||
|
struct OrphaningVertexBuffer : VertexBuffer<V> {
|
||||||
|
OrphaningVertexBuffer(GLuint program, std::vector<VertexAttrib<V>> attribs)
|
||||||
|
: VertexBuffer<V>{program, std::move(attribs), kVertexCount, kBufferType} {}
|
||||||
|
|
||||||
|
template <typename VertexIter,
|
||||||
|
typename = std::enable_if<std::is_convertible_v<typename std::iterator_traits<VertexIter>::value_type, V>>>
|
||||||
|
size_t AddVertexData(VertexIter begin, VertexIter end) {
|
||||||
|
this->bind();
|
||||||
|
|
||||||
|
auto dist = std::distance(begin, end);
|
||||||
|
if (nextVertex_ + dist >= kVertexCount) {
|
||||||
|
dglBufferData(GL_ARRAY_BUFFER,
|
||||||
|
kVertexCount * sizeof(V),
|
||||||
|
nullptr,
|
||||||
|
kBufferType);
|
||||||
|
nextVertex_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto start = nextVertex_;
|
||||||
|
V* mapped = reinterpret_cast<V*>(dglMapBufferRange(GL_ARRAY_BUFFER, start * sizeof(V), dist * sizeof(V), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
|
||||||
|
std::copy(begin, end, mapped);
|
||||||
|
dglUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
nextVertex_ += dist;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t kVertexCount{1 << 16};
|
||||||
|
static constexpr GLenum kBufferType{GL_STREAM_DRAW};
|
||||||
|
size_t nextVertex_{};
|
||||||
|
};
|
||||||
|
|
||||||
template <GLenum kType>
|
template <GLenum kType>
|
||||||
struct Shader {
|
struct Shader {
|
||||||
static_assert(kType == GL_VERTEX_SHADER || kType == GL_FRAGMENT_SHADER);
|
static_assert(kType == GL_VERTEX_SHADER || kType == GL_FRAGMENT_SHADER);
|
||||||
@ -141,7 +182,7 @@ private:
|
|||||||
template <typename V>
|
template <typename V>
|
||||||
struct ShaderProgram {
|
struct ShaderProgram {
|
||||||
explicit ShaderProgram(std::string_view vertexSrc, std::string_view fragmentSrc, std::vector<VertexAttrib<V>> attribs)
|
explicit ShaderProgram(std::string_view vertexSrc, std::string_view fragmentSrc, std::vector<VertexAttrib<V>> attribs)
|
||||||
: id_{dglCreateProgram()}, vertex_{vertexSrc}, fragment_{fragmentSrc}, vbo_{id_, std::move(attribs), MAX_POINTS_IN_POLY, GL_DYNAMIC_DRAW} {
|
: id_{dglCreateProgram()}, vertex_{vertexSrc}, fragment_{fragmentSrc}, vbo_{id_, std::move(attribs)} {
|
||||||
if (id_ == 0) {
|
if (id_ == 0) {
|
||||||
throw std::runtime_error("error creating GL program");
|
throw std::runtime_error("error creating GL program");
|
||||||
}
|
}
|
||||||
@ -170,8 +211,10 @@ struct ShaderProgram {
|
|||||||
dglUseProgram(0);
|
dglUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVertexData(size_t offset, size_t count, PosColorUV2Vertex const* vertices) {
|
template <typename VertexIter,
|
||||||
vbo_.UpdateData(offset, count, vertices);
|
typename = std::enable_if<std::is_convertible_v<typename std::iterator_traits<VertexIter>::value_type, V>>>
|
||||||
|
size_t addVertexData(VertexIter begin, VertexIter end) {
|
||||||
|
return vbo_.AddVertexData(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUniformMat4f(std::string const& name, glm::mat4x4 const& matrix) {
|
void setUniformMat4f(std::string const& name, glm::mat4x4 const& matrix) {
|
||||||
@ -212,6 +255,6 @@ private:
|
|||||||
MoveOnlyHolder<GLuint, DeleteProgram> id_;
|
MoveOnlyHolder<GLuint, DeleteProgram> id_;
|
||||||
Shader<GL_VERTEX_SHADER> vertex_;
|
Shader<GL_VERTEX_SHADER> vertex_;
|
||||||
Shader<GL_FRAGMENT_SHADER> fragment_;
|
Shader<GL_FRAGMENT_SHADER> fragment_;
|
||||||
VertexBuffer<V> vbo_;
|
OrphaningVertexBuffer<V> vbo_;
|
||||||
std::unordered_map<std::string, GLint> uniform_cache_;
|
std::unordered_map<std::string, GLint> uniform_cache_;
|
||||||
};
|
};
|
||||||
|
@ -165,6 +165,7 @@ DYNAEXTERN(glGetString);
|
|||||||
DYNAEXTERN(glGetStringi);
|
DYNAEXTERN(glGetStringi);
|
||||||
DYNAEXTERN(glGetUniformLocation);
|
DYNAEXTERN(glGetUniformLocation);
|
||||||
DYNAEXTERN(glLinkProgram);
|
DYNAEXTERN(glLinkProgram);
|
||||||
|
DYNAEXTERN(glMapBufferRange);
|
||||||
DYNAEXTERN(glPixelStorei);
|
DYNAEXTERN(glPixelStorei);
|
||||||
DYNAEXTERN(glPolygonOffset);
|
DYNAEXTERN(glPolygonOffset);
|
||||||
DYNAEXTERN(glReadPixels);
|
DYNAEXTERN(glReadPixels);
|
||||||
@ -177,6 +178,7 @@ DYNAEXTERN(glUniform1f);
|
|||||||
DYNAEXTERN(glUniform1i);
|
DYNAEXTERN(glUniform1i);
|
||||||
DYNAEXTERN(glUniform4f);
|
DYNAEXTERN(glUniform4f);
|
||||||
DYNAEXTERN(glUniformMatrix4fv);
|
DYNAEXTERN(glUniformMatrix4fv);
|
||||||
|
DYNAEXTERN(glUnmapBuffer);
|
||||||
DYNAEXTERN(glUseProgram);
|
DYNAEXTERN(glUseProgram);
|
||||||
DYNAEXTERN(glVertexAttribPointer);
|
DYNAEXTERN(glVertexAttribPointer);
|
||||||
DYNAEXTERN(glViewport);
|
DYNAEXTERN(glViewport);
|
||||||
|
Loading…
Reference in New Issue
Block a user