Minor refactoring

This commit is contained in:
Vladislav Khorev 2026-01-14 13:24:07 +03:00
parent 4cc6971542
commit dca38c986d
6 changed files with 93 additions and 104 deletions

View File

@ -109,6 +109,7 @@ namespace ZL
, glContext(nullptr) , glContext(nullptr)
, newTickCount(0) , newTickCount(0)
, lastTickCount(0) , lastTickCount(0)
, planetObject(renderer, taskManager, mainThreadHandler)
{ {
projectiles.reserve(maxProjectiles); projectiles.reserve(maxProjectiles);
for (int i = 0; i < maxProjectiles; ++i) { for (int i = 0; i < maxProjectiles; ++i) {
@ -370,8 +371,6 @@ namespace ZL
std::cout << "Init step 6 " << std::endl; std::cout << "Init step 6 " << std::endl;
planetObject.init(); planetObject.init();
planetObject.taskManager = &taskManager;
std::cout << "Init step 7 " << std::endl; std::cout << "Init step 7 " << std::endl;
//rockTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE)); //rockTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE));
@ -921,6 +920,7 @@ namespace ZL
#endif #endif
} }
render(); render();
mainThreadHandler.processMainThreadTasks();
} }
void Game::handleDown(int mx, int my) void Game::handleDown(int mx, int my)

View File

@ -12,7 +12,7 @@
namespace ZL { namespace ZL {
struct BoxCoords struct BoxCoords
{ {
Vector3f pos; Vector3f pos;
@ -29,9 +29,11 @@ namespace ZL {
void update(); void update();
void render(); void render();
bool shouldExit() const { return Environment::exitGameLoop; } bool shouldExit() const { return Environment::exitGameLoop; }
Renderer renderer;
TaskManager taskManager;
MainThreadHandler mainThreadHandler;
private: private:
void processTickCount(); void processTickCount();
void drawScene(); void drawScene();
@ -48,42 +50,16 @@ namespace ZL {
SDL_Window* window; SDL_Window* window;
SDL_GLContext glContext; SDL_GLContext glContext;
Renderer renderer;
size_t newTickCount; size_t newTickCount;
size_t lastTickCount; size_t lastTickCount;
//std::shared_ptr<Texture> rockTexture;
std::vector<BoxCoords> boxCoordsArr; std::vector<BoxCoords> boxCoordsArr;
std::vector<VertexRenderStruct> boxRenderArr; std::vector<VertexRenderStruct> boxRenderArr;
//std::shared_ptr<Texture> buttonTexture;
//VertexRenderStruct button;
//std::shared_ptr<Texture> musicVolumeBarTexture;
//VertexRenderStruct musicVolumeBar;
//std::shared_ptr<Texture> musicVolumeBarButtonTexture;
//VertexRenderStruct musicVolumeBarButton;
//bool isDraggingVolume = false;
/*
float velocitySlider = 0.0f;
float volumeBarMinX = 1190.0f;
float volumeBarMaxX = 1200.0f;
float volumeBarMinY = 100.0f;
float volumeBarMaxY = 600.0f;*/
//float musicVolumeBarButtonButtonCenterX = 1195.0f;
//float musicVolumeBarButtonButtonRadius = 25.0f;
//void UpdateVolumeFromMouse(int mouseX, int mouseY);
//void UpdateVolumeKnob();
static const size_t CONST_TIMER_INTERVAL = 10; static const size_t CONST_TIMER_INTERVAL = 10;
static const size_t CONST_MAX_TIME_INTERVAL = 1000; static const size_t CONST_MAX_TIME_INTERVAL = 1000;
@ -111,8 +87,7 @@ namespace ZL {
int maxProjectiles = 32; int maxProjectiles = 32;
std::vector<Vector3f> shipLocalEmissionPoints; std::vector<Vector3f> shipLocalEmissionPoints;
TaskManager taskManager;
bool shipAlive = true; bool shipAlive = true;
bool gameOver = false; bool gameOver = false;
std::vector<bool> boxAlive; std::vector<bool> boxAlive;

View File

@ -57,9 +57,11 @@ namespace ZL {
return rot; return rot;
} }
PlanetObject::PlanetObject() PlanetObject::PlanetObject(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler)
: renderer(iRenderer),
taskManager(iTaskManager),
mainThreadHandler(iMainThreadHandler)
{ {
} }
void PlanetObject::init() { void PlanetObject::init() {
@ -101,7 +103,7 @@ namespace ZL {
float movementThreshold = 1.0f; float movementThreshold = 1.0f;
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold
&& !triangleIndicesToDraw.empty()) { && !triangleIndicesToDraw.empty()) {
processMainThreadTasks(); // Все равно обрабатываем очередь OpenGL задач //processMainThreadTasks(); // Все равно обрабатываем очередь OpenGL задач
return; return;
} }
lastUpdatePos = Environment::shipPosition; lastUpdatePos = Environment::shipPosition;
@ -117,13 +119,13 @@ namespace ZL {
planetStones.statuses[triIdx] = ChunkStatus::Generating; planetStones.statuses[triIdx] = ChunkStatus::Generating;
// Отправляем тяжелую математику в TaskManager // Отправляем тяжелую математику в TaskManager
taskManager->EnqueueBackgroundTask([this, triIdx]() { taskManager.EnqueueBackgroundTask([this, triIdx]() {
// Выполняется в фоновом потоке: только генерация геометрии в RAM // Выполняется в фоновом потоке: только генерация геометрии в RAM
float scaleModifier = 1.0f; float scaleModifier = 1.0f;
VertexDataStruct generatedData = planetStones.inflateOneDataOnly(triIdx, scaleModifier); VertexDataStruct generatedData = planetStones.inflateOneDataOnly(triIdx, scaleModifier);
// Передаем задачу на загрузку в GPU в очередь главного потока // Передаем задачу на загрузку в GPU в очередь главного потока
this->EnqueueMainThreadTask([this, triIdx, data = std::move(generatedData)]() mutable { this->mainThreadHandler.EnqueueMainThreadTask([this, triIdx, data = std::move(generatedData)]() mutable {
// Проверяем актуальность: если треугольник всё еще в списке видимых // Проверяем актуальность: если треугольник всё еще в списке видимых
auto it = std::find(triangleIndicesToDraw.begin(), triangleIndicesToDraw.end(), triIdx); auto it = std::find(triangleIndicesToDraw.begin(), triangleIndicesToDraw.end(), triIdx);
if (it != triangleIndicesToDraw.end()) { if (it != triangleIndicesToDraw.end()) {
@ -164,22 +166,7 @@ namespace ZL {
triangleIndicesToDraw = std::move(newIndices); triangleIndicesToDraw = std::move(newIndices);
// 5. Выполняем одну задачу из очереди OpenGL (RefreshVBO и т.д.) // 5. Выполняем одну задачу из очереди OpenGL (RefreshVBO и т.д.)
processMainThreadTasks(); //processMainThreadTasks();
/*
float movementThreshold = 1.0f;
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold && !triangleIndicesToDraw.empty()) {
return;
}
lastUpdatePos = Environment::shipPosition;
auto newIndices = planetData.getTrianglesUnderCameraNew2(Environment::shipPosition);
// Сортировка важна для сравнения векторов
std::sort(newIndices.begin(), newIndices.end());
if (newIndices != triangleIndicesToDraw) {
triangleIndicesToDraw = std::move(newIndices);
}*/
} }

View File

@ -21,6 +21,7 @@
namespace ZL { namespace ZL {
class TaskManager; class TaskManager;
class MainThreadHandler;
class PlanetObject { class PlanetObject {
public: public:
@ -42,10 +43,12 @@ namespace ZL {
Vector3f lastUpdatePos; Vector3f lastUpdatePos;
TaskManager* taskManager = nullptr; // External items, set outside
Renderer& renderer;
TaskManager& taskManager;
MainThreadHandler& mainThreadHandler;
public: public:
PlanetObject(); PlanetObject(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler);
void init(); void init();
void update(float deltaTimeMs); void update(float deltaTimeMs);
@ -56,32 +59,6 @@ namespace ZL {
void drawAtmosphere(Renderer& renderer); void drawAtmosphere(Renderer& renderer);
float distanceToPlanetSurface(const Vector3f& viewerPosition); float distanceToPlanetSurface(const Vector3f& viewerPosition);
std::queue<std::function<void()>> mainThreadTasks;
std::mutex mainThreadMutex;
void EnqueueMainThreadTask(std::function<void()> task) {
std::lock_guard<std::mutex> lock(mainThreadMutex);
mainThreadTasks.push(task);
}
// Выполнение задач по одной (или пачкой) за кадр
void processMainThreadTasks() {
std::function<void()> task;
// Извлекаем только одну задачу, чтобы не блокировать update надолго
{
std::lock_guard<std::mutex> lock(mainThreadMutex);
if (!mainThreadTasks.empty()) {
task = std::move(mainThreadTasks.front());
mainThreadTasks.pop();
}
}
if (task) {
task(); // Здесь выполняется RefreshVBO или загрузка текстуры
}
}
}; };
} // namespace ZL } // namespace ZL

View File

@ -0,0 +1,50 @@
#include "TaskManager.h"
namespace ZL
{
TaskManager::TaskManager(size_t threadCount) {
workGuard = std::make_unique<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(ioContext.get_executor());
for (size_t i = 0; i < threadCount; ++i) {
workers.emplace_back([this]() {
ioContext.run();
});
}
}
void TaskManager::EnqueueBackgroundTask(std::function<void()> task) {
boost::asio::post(ioContext, task);
}
TaskManager::~TaskManager() {
workGuard.reset(); // Ðàçðåøàåì ioContext.run() çàâåðøèòüñÿ, êîãäà çàäà÷ íå îñòàíåòñÿ
ioContext.stop(); // Îïöèîíàëüíî: íåìåäëåííàÿ îñòàíîâêà
for (auto& t : workers) {
if (t.joinable()) t.join();
}
}
void MainThreadHandler::EnqueueMainThreadTask(std::function<void()> task) {
std::lock_guard<std::mutex> lock(mainThreadMutex);
mainThreadTasks.push(task);
}
void MainThreadHandler::processMainThreadTasks() {
std::function<void()> task;
// Èçâëåêàåì òîëüêî îäíó çàäà÷ó, ÷òîáû íå áëîêèðîâàòü update íàäîëãî
{
std::lock_guard<std::mutex> lock(mainThreadMutex);
if (!mainThreadTasks.empty()) {
task = std::move(mainThreadTasks.front());
mainThreadTasks.pop();
}
}
if (task) {
task(); // Çäåñü âûïîëíÿåòñÿ RefreshVBO èëè çàãðóçêà òåêñòóðû
}
}
}

View File

@ -4,6 +4,8 @@
#include <vector> #include <vector>
#include <thread> #include <thread>
#include <memory> #include <memory>
#include <queue>
namespace ZL { namespace ZL {
@ -14,30 +16,28 @@ namespace ZL {
std::vector<std::thread> workers; std::vector<std::thread> workers;
public: public:
//TaskManager(size_t threadCount = std::thread::hardware_concurrency()) { //TaskManager(size_t threadCount = std::thread::hardware_concurrency());
TaskManager(size_t threadCount = 2) { TaskManager(size_t threadCount = 2);
workGuard = std::make_unique<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(ioContext.get_executor());
for (size_t i = 0; i < threadCount; ++i) {
workers.emplace_back([this]() {
ioContext.run();
});
}
}
// Ìåòîä äëÿ äîáàâëåíèÿ ôîíîâîé çàäà÷è // Ìåòîä äëÿ äîáàâëåíèÿ ôîíîâîé çàäà÷è
void EnqueueBackgroundTask(std::function<void()> task) { void EnqueueBackgroundTask(std::function<void()> task);
boost::asio::post(ioContext, task);
}
// Graceful shutdown // Graceful shutdown
~TaskManager() { ~TaskManager();
workGuard.reset(); // Ðàçðåøàåì ioContext.run() çàâåðøèòüñÿ, êîãäà çàäà÷ íå îñòàíåòñÿ };
ioContext.stop(); // Îïöèîíàëüíî: íåìåäëåííàÿ îñòàíîâêà
for (auto& t : workers) {
if (t.joinable()) t.join(); class MainThreadHandler
} {
} private:
std::queue<std::function<void()>> mainThreadTasks;
std::mutex mainThreadMutex;
public:
void EnqueueMainThreadTask(std::function<void()> task);
// Âûïîëíåíèå çàäà÷ ïî îäíîé (èëè ïà÷êîé) çà êàäð
void processMainThreadTasks();
}; };
} // namespace ZL } // namespace ZL