Basic scene loop

This commit is contained in:
Dynamitos
2025-01-24 21:54:38 +01:00
parent ff9ebb916f
commit 3cbc73ebfe
5 changed files with 71 additions and 54 deletions
+17 -16
View File
@@ -16,25 +16,23 @@ ThreadPool::~ThreadPool()
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
queueCV.notify_all(); queueCV.notify_all();
} }
for(auto& worker : workers) for (auto& worker : workers)
{ {
worker.join(); worker.join();
} }
} }
void ThreadPool::addJob(std::function<void()>&& job) void ThreadPool::runBatch(Batch&& batch)
{ {
std::unique_lock l(queueLock);
taskQueue.push_back(job);
queueCV.notify_one();
}
void ThreadPool::waitIdle()
{
while(true)
{ {
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
if(taskQueue.empty()) taskQueue.push_back(batch);
queueCV.notify_one();
}
while (true)
{
std::unique_lock l(queueLock);
if (taskQueue.empty())
return; return;
completedCV.wait(l); completedCV.wait(l);
} }
@@ -42,24 +40,27 @@ void ThreadPool::waitIdle()
void ThreadPool::work() void ThreadPool::work()
{ {
while(running) while (running)
{ {
std::function<void()> job; std::function<void()> job;
{ {
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
if(taskQueue.empty()) if (taskQueue.front().jobs.empty())
{ {
queueCV.wait(l); queueCV.wait(l);
continue; continue;
} }
job = taskQueue.front(); job = taskQueue.front().jobs.front();
taskQueue.pop_front(); taskQueue.front().jobs.pop_front();
} }
job(); job();
{ {
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
if (taskQueue.front().jobs.empty())
{
taskQueue.pop_front();
completedCV.notify_one(); completedCV.notify_one();
} }
} }
}
} }
+7 -3
View File
@@ -4,19 +4,23 @@
#include <list> #include <list>
#include <thread> #include <thread>
struct Batch
{
std::list<std::function<void()>> jobs;
};
class ThreadPool class ThreadPool
{ {
public: public:
ThreadPool(uint32_t numWorkers = std::thread::hardware_concurrency()); ThreadPool(uint32_t numWorkers = std::thread::hardware_concurrency());
~ThreadPool(); ~ThreadPool();
void addJob(std::function<void()>&& job); void runBatch(Batch&& batch);
void waitIdle();
private: private:
std::atomic_bool running = true; std::atomic_bool running = true;
void work(); void work();
std::mutex queueLock; std::mutex queueLock;
std::condition_variable queueCV; std::condition_variable queueCV;
std::condition_variable completedCV; std::condition_variable completedCV;
std::list<std::function<void()>> taskQueue; std::list<Batch> taskQueue;
std::vector<std::thread> workers; std::vector<std::thread> workers;
}; };
+12 -6
View File
@@ -1,18 +1,24 @@
#include "scene/BVH.h" #include "scene/BVH.h"
#include "scene/Scene.h"
#include "util/ModelLoader.h" #include "util/ModelLoader.h"
#include "window/Window.h" #include "window/Window.h"
int main() int main()
{ {
Scene scene; Scene scene;
Window window; Window window(1920, 1080);
scene.render(
Camera{
.position = glm::vec3(10, 0, 0),
.direction = glm::vec3(-1, 0, 0),
},
RenderParameter{
.width = 1920,
.height = 1080,
.numSamples = 10000,
});
while (true) while (true)
{ {
// IMGUI....
if (Imgui.Button())
{
scene.render();
}
window.update(scene.getImage()); window.update(scene.getImage());
} }
return 0; return 0;
+22 -16
View File
@@ -1,34 +1,40 @@
#include "Scene.h" #include "Scene.h"
Scene::Scene(glm::vec3 cameraPos, glm::vec3 cameraDirection) : cameraPos(cameraPos), cameraDirection(cameraDirection) {} Scene::Scene() {}
Scene::~Scene() {} Scene::~Scene() {}
void Scene::render(int width, int height, int numSamples) void Scene::render(Camera cam, RenderParameter params)
{ {
pendingCancel = true;
worker.join();
pendingCancel = false;
worker = std::thread( worker = std::thread(
[&]() [&]()
{ {
image.clear(); image.clear();
accumulator.clear(); accumulator.clear();
image.resize(width * height * 3); image.resize(params.width * params.height * 3);
for (int samp = 0; samp < numSamples; ++samp) accumulator.resize(params.width * params.height * 3);
for (int samp = 0; samp < params.numSamples; ++samp)
{ {
std::function<void()> job = [&]() if (pendingCancel)
{
std::vector<unsigned char> localAccumulator(width * height * 3);
for (int w = 0; w < width; ++w)
{
for (int h = 0; h < height; ++h)
{
if (cancel)
return; return;
bvh.traceRay(); Batch batch;
for (int w = 0; w < params.width; ++w)
{
for (int h = 0; h < params.height; ++h)
{
batch.jobs.push_back(
[&]()
{
Ray r = Ray();
bvh.traceRay(r);
});
} }
} }
// lock image threadPool.runBatch(std::move(batch));
// add result to image std::memcpy(image.data(), accumulator.data(), accumulator.size());
};
} }
}); });
} }
+12 -12
View File
@@ -2,26 +2,26 @@
#include "BVH.h" #include "BVH.h"
#include "window/Window.h" #include "window/Window.h"
#include "util/Camera.h" #include "util/Camera.h"
#include "ThreadPool.h"
struct RenderParameter
{
int width;
int height;
int numSamples;
};
/// <summary>
/// Ray1
/// Ray2
/// Ray3
/// Ray4
/// Ray5
/// GammaResolve
/// Ray1
/// Ray2
/// Ray3
/// </summary>
class Scene class Scene
{ {
public: public:
Scene(); Scene();
~Scene(); ~Scene();
void render(Camera cam, int width, int height, int numSamples); void render(Camera cam, RenderParameter params);
constexpr const std::vector<unsigned char>& getImage() const { return image; } constexpr const std::vector<unsigned char>& getImage() const { return image; }
private: private:
std::atomic_bool pendingCancel = false;
ThreadPool threadPool;
std::thread worker;
// the thing being displayed // the thing being displayed
std::vector<unsigned char> image; std::vector<unsigned char> image;
// radiance accumulator // radiance accumulator