Performance optimization.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled

This commit is contained in:
2025-05-12 11:38:28 -04:00
parent 7ea4b8696e
commit 6f99689add
9 changed files with 76 additions and 63 deletions

View File

@@ -47,7 +47,7 @@ if (WIN32)
)
endif()
set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
#set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
file(COPY "assets" DESTINATION "${PROJECT_BINARY_DIR}")
file(GLOB_RECURSE ASSETS "assets/*")

View File

@@ -72,15 +72,6 @@ vec4 DefaultInstanced() {
return gl_ModelViewProjectionMatrix * vec4(world_pos, 0.0, 1.0);
}
vec4 FillRectInstanced() {
vec2 instance_pos = a_instance_position + vec2(0.0, a_instance_size.y);
vec2 scaled = a_vertex_position * a_instance_size;
vec2 world_pos = scaled + instance_pos;
v_color = a_instance_color;
return gl_ModelViewProjectionMatrix * vec4(world_pos, 0.0, 1.0);
}
void main() {
GL_TEXTURE0_COORD = gl_MultiTexCoord0.xy;
GL_TEXTURE1_COORD = gl_MultiTexCoord1.xy;
@@ -156,7 +147,7 @@ void main() {
*/
if (JGL_RENDERING_ROUTINE == J2D_FillRect && JGL_INSTANCED_RENDERING)
gl_Position = FillRectInstanced();
gl_Position = DefaultInstanced();
else
gl_Position = Default();
}

View File

@@ -16,6 +16,7 @@
#include <Color4.hpp>
#include <JGL/types/Texture.h>
#include <JGL/types/Enums.h>
#include <JGL/types/Instance.h>
#include <JGL/types/FontCache.h>
#include <JGL/types/Font.h>
#include <JGL/types/RenderTarget.h>
@@ -398,8 +399,7 @@ namespace JGL::J2D {
void OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness = 1, int subdivisions = 8);
void FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions = 8);
void BatchFillRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, const size_t& rect_count);
void BatchFillRect(const Instance2D* instances, const size_t& instance_count);
void BatchFillCircle(const Color4 *colors, const Vector2* positions, float* radii, unsigned int subdivisions, const size_t& circle_count);
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <Colors.hpp>
#include <J3ML/LinearAlgebra/Vector2.hpp>
#include <J3ML/LinearAlgebra/Matrix4x4.hpp>
namespace JGL {
struct Instance2D;
struct Instance3D;
}
/// Information provided to JGL for each instance of an object you're rendering in a batch.
/// @note This is non-negotiable. This information is interleaved in *the same buffer* in v-ram for performance reasons - Redacted.
struct JGL::Instance2D {
public:
Color4 color;
Vector2 position;
Vector2 size;
Vector2 scale;
float rotation;
public:
/// @param position The position of the instance in world space.
/// @param size The size of the instance.
/// @param scale A multiplier to be applied to the size.
/// @param rotation The rotation in radians.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4.
/// @note If the thing you're drawing is textured you probably want Colors::White
Instance2D(const Color4& color, const Vector2& position, const Vector2& size, const Vector2& scale = Vector2::One, float rotation = 0.0f) :
color(color), position(position), size(size), scale(scale), rotation(rotation) {};
Instance2D() = default;
~Instance2D() = default;
};
struct JGL::Instance3D {
public:
Matrix4x4 instance_matrix;
Color4 color;
public:
/// @param instance_matrix A matrix containing rotation matrix, position, and scale.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4.
/// @note If the thing you're drawing is textured you probably want Colors::White
Instance3D(const Matrix4x4& instance_matrix, const Color4& color) : instance_matrix(instance_matrix), color(color) {};
Instance3D() = default;
~Instance3D() = default;
};

View File

@@ -15,9 +15,7 @@ using namespace JGL;
using JGL::Font;
float fps = 0.0f;
std::vector<Vector2> rect_pos;
std::vector<Vector2> rect_size;
std::vector<Color4> rect_colors;
std::vector<Instance2D> rect_instances;
/// A draggable 2D point that highlights when moused over and when clicked.
class Gizmo
{
@@ -142,11 +140,8 @@ public:
shader = new Shader(std::filesystem::path("assets/shader_programs/test_vertex.glsl"), std::filesystem::path("assets/shader_programs/test_fragment.glsl"),
{{"a_vertex_position", 0}, {"a_instance_position", 1}, {"a_instance_size", 2}, {"a_instance_color", 3}});
for (unsigned int i = 0; i < 1000000; i++) {
rect_pos.emplace_back(420, 420);
rect_size.emplace_back(20, 20);
rect_colors.emplace_back(Colors::Red);
}
for (unsigned int i = 0; i < 100; i++)
rect_instances.emplace_back(Colors::Red, Vector2(420, 420), Vector2(20, 20));
}
EulerAngleXYZ textAngle = {0,0,0};
@@ -202,7 +197,7 @@ public:
J2D::Begin(j2d_render_target, shader, true);
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
J2D::BatchFillRect(rect_colors.data(), rect_pos.data(), rect_size.data(), rect_pos.size());
J2D::BatchFillRect(rect_instances.data(), rect_instances.size());
J2D::DrawSprite(image, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawMirrorSprite(image, {400, 300}, Direction::Horizontal | Direction::Vertical, sprite_radians, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawPartialSprite(image, Vector2(225, 300), Vector2(image->GetDimensions()) * 0.25, Vector2(image->GetDimensions()) * 0.75, sprite_radians, {0.5, 0.5}, {1,1}, Colors::White);

View File

@@ -47,7 +47,8 @@ void JGL::ShapeCache::Init() {
cube_normal_data = new VRamList(vertex_normals.data(), vertex_normals.size());
if (!square_origin_topleft_vertex_data) {
std::array<Vector2, 4> square_vertices = { Vector2(0, 0), {1, 0}, {1, -1}, {0, -1} };
//std::array<Vector2, 4> square_vertices = { Vector2(0, 0), {1, 0}, {1, -1}, {0, -1} };
std::array<Vector2, 4> square_vertices = { Vector2(0, 0), {0, 1}, {1, 1}, {1, 0} };
square_origin_topleft_vertex_data = new VRamList(square_vertices.data(), square_vertices.size());
}
if (!j2d_default_normal_data) {

View File

@@ -1,5 +1,6 @@
#include <JGL/JGL.h>
#include <JGL/logger/logger.h>
#include <JGL/types/Instance.h>
#include <J3ML/Algorithm/Bezier.hpp>
#include "internals/internals.h"
@@ -262,14 +263,14 @@ void J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& si
}
void J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
BatchFillRect(&color, &pos, &size, 1);
Instance2D rect(color, pos, size);
BatchFillRect(&rect, 1);
}
void J2D::BatchFillRect(const Color4* colors, const Vector2* positions, const Vector2* sizes, const size_t& rect_count) {
void J2D::BatchFillRect(const Instance2D* instances, const size_t& instance_count) {
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
if (rect_count <= 0)
if (instance_count <= 0)
return;
if (current_state.current_shader)
@@ -277,14 +278,14 @@ void J2D::BatchFillRect(const Color4* colors, const Vector2* positions, const Ve
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::square_origin_topleft_vertex_data->Handle());
if (rect_count == 1 || !supports_instanced || !current_state.current_shader) {
if (instance_count == 1 || !supports_instanced || !current_state.current_shader) {
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
for (size_t i = 0; i < rect_count; i++) {
for (size_t i = 0; i < instance_count; i++) {
glPushMatrix();
glColor4ubv(colors[i].ptr());
glTranslatef(positions[i].x, positions[i].y + sizes[i].y, 0);
glScalef(sizes[i].x, sizes[i].y, 1);
glColor4ubv(instances[i].color.ptr());
glTranslatef(instances[i].position.x, instances[i].position.y, 0);
glScalef(instances[i].size.x, instances[i].size.y, 1);
glDrawArrays(GL_QUADS, 0, 4);
glPopMatrix();
}
@@ -294,33 +295,26 @@ void J2D::BatchFillRect(const Color4* colors, const Vector2* positions, const Ve
else {
current_state.current_shader->SetBool("JGL_INSTANCED_RENDERING", true);
std::vector<Instance> instances(rect_count);
Instance* ptr = instances.data();
// Shader does translation to top left corner in this path - Redacted.
for (size_t i = 0; i < rect_count; ++i)
ptr[i] = { positions[i], sizes[i], colors[i] };
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), nullptr);
glVertexAttribDivisorARB(0, 0);
// * 5 because 4x float & 4x uint8_t = sizeof(float) - Redacted.
VRamList instance_buffer((GLfloat*) instances.data(), instances.size() * 5, Stream);
VRamList instance_buffer((GLfloat*) instances, instance_count * (sizeof(Instance2D) / sizeof(GLfloat)), Stream);
glBindBuffer(GL_ARRAY_BUFFER, instance_buffer.Handle());
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Instance), (GLvoid*) offsetof(Instance, position));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, position));
glVertexAttribDivisorARB(1, 1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Instance), (GLvoid*) offsetof(Instance, size));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, size));
glVertexAttribDivisorARB(2, 1);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Instance), (GLvoid*) offsetof(Instance, color));
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Instance2D), (GLvoid*) offsetof(Instance2D, color));
glVertexAttribDivisorARB(3, 1);
glDrawArraysInstancedARB(GL_QUADS, 0, 4, rect_count);
glDrawArraysInstancedARB(GL_QUADS, 0, 4, instance_count);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
@@ -368,8 +362,6 @@ void J2D::FillGradientRect(const Color4& top_left_color, const Color4& bottom_le
void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
std::array<Color4, 4> colors = { color, color, color, color };
std::array<Vector2, 2> rect_positions = { Vector2(pos.x + radius, pos.y), {pos.x, pos.y + radius} };
std::array<Vector2, 2> rect_sizes = { Vector2(size.x - 2 * radius, size.y), {size.x, size.y - 2 * radius} };
std::array<float, 4> circle_radii = { radius, radius, radius, radius };
std::array<Vector2, 4> circle_positions
{
@@ -380,7 +372,8 @@ void J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2
if (current_state.current_shader)
current_state.current_shader->SetInt("JGL_RENDERING_ROUTINE", RENDERING_ROUTINE_ID::J2D_FillRoundedRect);
J2D::BatchFillRect(colors.data(), rect_positions.data(), rect_sizes.data(), 2);
std::array<Instance2D, 2> rect_instances { Instance2D(color,Vector2(pos.x + radius, pos.y), Vector2(size.x - 2 * radius, size.y)), Instance2D(color, Vector2(pos.x, pos.y + radius), Vector2(size.x, size.y - 2 * radius)) };
J2D::BatchFillRect(rect_instances.data(), rect_instances.size());
J2D::BatchFillCircle(colors.data(), circle_positions.data(), circle_radii.data(), subdivisions, 4);
if (current_state.current_shader)

View File

@@ -97,17 +97,6 @@ namespace JGL {
inline StateStack state_stack;
inline Vector2i window_size;
inline bool supports_instanced = true;
struct Instance {
public:
Vector2 position;
Vector2 size;
Color4 color;
public:
Instance(const Vector2& position, const Vector2& size, const Color4& color) : position(position), size(size), color(color) {}
Instance() = default;
~Instance() = default;
};
}
namespace JGL::J2D {

View File

@@ -67,7 +67,6 @@ size_t JGL::VRamList::Size() const {
void JGL::VRamList::SetData(void* data, const long& length) {
bool should_resize = (this->byte_count != length * 4);
if (should_resize) {
glDeleteBuffers(1, &list_handle);
@@ -89,12 +88,8 @@ void JGL::VRamList::SetData(void* data, const long& length) {
size_t element_size = element_array_buffer ? sizeof(GLuint) : sizeof(GLfloat);
if (usage_hint != Fixed)
glBufferData(GL_ARRAY_BUFFER, length * element_size, nullptr, usage_hint);
glBufferSubData(buffer_type, 0, length * element_size, data);
glBindBuffer(buffer_type, current_buffer);
}
void JGL::VRamList::UpdateData(void* data, const long& offset, const long& length) {