un-fix threads; more refactoring

main
Clyne 7 months ago
parent 7d174816fe
commit 577d44970b
Signed by: clyne
GPG Key ID: 1B74EE6C49C96795

@ -1,7 +1,6 @@
constexpr unsigned Width = 1000; constexpr unsigned Width = 1000;
constexpr double Aspect = 16.0 / 9.0; constexpr double Aspect = 16.0 / 9.0;
constexpr unsigned Height = Width / Aspect; constexpr unsigned Height = Width / Aspect;
constexpr unsigned Threads = 3;
#include "color.h" #include "color.h"
#include "ray.h" #include "ray.h"
@ -26,14 +25,17 @@ constexpr unsigned Threads = 3;
static View Camera; static View Camera;
static World world; static World world;
static int threads = 4;
static int SamplesPerPixel = 20; static int SamplesPerPixel = 20;
static float Daylight = 0.5f; static float Daylight = 0.5f;
static std::unique_ptr<Renderer<Threads>> renderer; static std::unique_ptr<Renderer> renderer;
static std::chrono::time_point<std::chrono::high_resolution_clock> renderStart; static std::chrono::time_point<std::chrono::high_resolution_clock> renderStart;
static std::chrono::duration<double> renderTime; static std::chrono::duration<double> renderTime;
static color ray_color(const ray& r, int depth = 50); static color ray_color(const ray& r, int depth = 50);
static void initiateRender(SDL_Surface *canvas); static void initiateRender(SDL_Surface *canvas);
static void showObjectControls(int index, Sphere& o);
static void addRandomObject();
int main() int main()
{ {
@ -47,10 +49,10 @@ int main()
ImGui_ImplSDL2_InitForSDLRenderer(window, painter); ImGui_ImplSDL2_InitForSDLRenderer(window, painter);
ImGui_ImplSDLRenderer2_Init(painter); ImGui_ImplSDLRenderer2_Init(painter);
world.add(point3( 0.00, -100.50, -1.0), 100.0, Material::Lambertian, color(0.5, 1.0, 0.5)); world.add(point3(0.00, -100.50, -1.0), 100.0,
world.add(point3(-0.50, 0.00, -1.2), 0.5, Material::Dielectric, color(1.0, 0.8, 0.8)); Material::Lambertian, color(0.5, 1.0, 0.5));
world.add(point3( 0.50, 0.00, -1.0), 0.5, Material::Metal, color(0.5, 0.5, 0.5)); for (auto i : std::views::iota(0, 10))
world.add(point3(-0.05, -0.35, -0.7), 0.1, Material::Metal, color(0.8, 0.6, 0.0)); addRandomObject();
std::cout << "Spawning threads..." << std::endl; std::cout << "Spawning threads..." << std::endl;
initiateRender(canvas); initiateRender(canvas);
@ -73,11 +75,17 @@ int main()
ImGui::Begin("settings", nullptr, ImGuiWindowFlags_AlwaysAutoResize); ImGui::Begin("settings", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::SliderFloat("fov", &Camera.fieldOfView, 10, 160); ImGui::SliderFloat("fov", &Camera.fieldOfView, 10, 160);
ImGui::SetNextItemWidth(100); ImGui::InputDouble("X", &Camera.camera.x(), 0.1, 0.05, "%.2lf"); ImGui::SameLine(); ImGui::SetNextItemWidth(60);
ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble("Y", &Camera.camera.y(), 0.1, 0.05, "%.2lf"); ImGui::InputInt("T", &threads);
ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble("Z", &Camera.camera.z(), 0.1, 0.05, "%.2lf"); ImGui::SetNextItemWidth(100);
ImGui::InputDouble("X", &Camera.camera.x(), 0.1, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble("Y", &Camera.camera.y(), 0.1, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble("Z", &Camera.camera.z(), 0.1, 0.05, "%.2lf");
ImGui::SliderInt("samples", &SamplesPerPixel, 1, 200); ImGui::SliderInt("samples", &SamplesPerPixel, 1, 200);
ImGui::SliderFloat("shade", &Daylight, 0.f, 1.f); ImGui::SliderFloat("shade", &Daylight, 0.f, 1.f);
if (ImGui::Button("recalculate")) { if (ImGui::Button("recalculate")) {
initiateRender(canvas); initiateRender(canvas);
} }
@ -94,6 +102,7 @@ int main()
renderer->stop(); renderer->stop();
run = false; run = false;
} }
if (*renderer) { if (*renderer) {
SDL_DestroyTexture(tex); SDL_DestroyTexture(tex);
tex = SDL_CreateTextureFromSurface(painter, canvas); tex = SDL_CreateTextureFromSurface(painter, canvas);
@ -114,35 +123,13 @@ int main()
ImGui::End(); ImGui::End();
ImGui::Begin("balls", nullptr, ImGuiWindowFlags_NoResize); { ImGui::Begin("balls", nullptr, ImGuiWindowFlags_NoResize); {
char radius[] = "radius 0"; std::ranges::for_each(
char mat[] = "mat 0"; std::views::zip(std::views::iota(0),
char xpos[] = "x 0"; std::views::drop(world.objects, 1)),
char ypos[] = "y 0"; [](auto io) { std::apply(showObjectControls, io); });
char zpos[] = "z 0";
for (auto& o : std::views::drop(world.objects, 1)) {
ImGui::SetNextItemWidth(200);
ImGui::Combo(mat, reinterpret_cast<int *>(&o.M),
"Lambertian\0Metal\0Dielectric\0");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble(radius, &o.radius, 0.1, 0.05, "%.2lf");
ImGui::SetNextItemWidth(100);
ImGui::InputDouble(xpos, &o.center.x(), 0.05, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble(ypos, &o.center.y(), 0.1, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble(zpos, &o.center.z(), 0.1, 0.05, "%.2lf");
radius[7]++;
mat[4]++;
xpos[2]++;
ypos[2]++;
zpos[2]++;
}
if (ImGui::Button("add")) { if (ImGui::Button("add")) {
const point3 pos = vec3::random() * vec3(4, 1.5, 4) - vec3(2, 0, 4); addRandomObject();
const color col = vec3::random();
world.add(pos, randomN() * 0.5 + 0.1, Material::Lambertian, col);
initiateRender(canvas); initiateRender(canvas);
} }
if (ImGui::Button("del")) { if (ImGui::Button("del")) {
@ -200,5 +187,37 @@ void initiateRender(SDL_Surface *canvas)
}; };
Camera.recalculate(); Camera.recalculate();
renderer.reset(new Renderer<Threads>(func, Width, Height, (uint32_t *)canvas->pixels)); threads = std::clamp(threads, 1, Renderer::MaxThreads);
renderer.reset(new Renderer(threads, func, Width, Height,
(uint32_t *)canvas->pixels));
} }
void showObjectControls(int index, Sphere& o)
{
const auto idx = std::to_string(index);
ImGui::SetNextItemWidth(200);
ImGui::Combo((std::string("mat") + idx).c_str(), reinterpret_cast<int *>(&o.M),
"Lambertian\0Metal\0Dielectric\0");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble((std::string("radius") + idx).c_str(),
&o.radius, 0.1, 0.05, "%.2lf");
ImGui::SetNextItemWidth(100);
ImGui::InputDouble((std::string("x") + idx).c_str(),
&o.center.x(), 0.05, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble((std::string("y") + idx).c_str(),
&o.center.y(), 0.1, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble((std::string("z") + idx).c_str(),
&o.center.z(), 0.1, 0.05, "%.2lf");
}
void addRandomObject()
{
const point3 pos = vec3::random() * vec3(6, 0.8, 3) - vec3(3, 0, 3.8);
const color col = vec3::random();
const auto mat = (int)(randomN() * ((int)Material::Undefined - 1));
world.add(pos, randomN() * 0.3 + 0.05, (Material)mat, col);
}

@ -6,7 +6,7 @@
inline double randomN() inline double randomN()
{ {
static std::uniform_real_distribution<double> distribution (0.0, 1.0); static std::uniform_real_distribution<double> distribution (0.0, 1.0);
static std::mt19937 generator; static std::mt19937 generator (std::random_device{}());
return distribution(generator); return distribution(generator);
} }

@ -1,3 +1,6 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
@ -5,28 +8,32 @@
#include <semaphore> #include <semaphore>
#include <thread> #include <thread>
template<int Threads>
class Renderer class Renderer
{ {
std::counting_semaphore<Threads> Workers; public:
static constexpr int MaxThreads = 64;
private:
int N;
std::counting_semaphore<MaxThreads> Workers;
std::atomic_uint processed; std::atomic_uint processed;
unsigned total; unsigned total;
std::atomic_bool Stop; std::atomic_bool Stop;
std::unique_ptr<std::thread> primary; std::unique_ptr<std::thread> primary;
public: public:
Renderer(auto func, unsigned Width, unsigned Height, auto pbuf): Renderer(int n, auto func, unsigned width, unsigned height, auto pbuf):
Workers(Threads), processed(0), total(Threads * 8) N(n), Workers(N), processed(0), total(N * 8)
{ {
Stop.store(false); Stop.store(false);
auto threads = std::views::transform( auto threads = std::views::transform(
std::views::chunk( std::views::chunk(
std::views::cartesian_product( std::views::cartesian_product(
std::views::iota(0u, Width), std::views::iota(0u, width),
std::views::iota(0u, Height), std::views::iota(0u, height),
std::views::single(pbuf)), std::views::single(pbuf)),
Width * Height / total), width * height / total),
[=, this](auto chunk) { return std::thread([=, this] { worker(func, chunk); }); }); [=, this](auto chunk) { return std::thread([=, this] { worker(func, chunk); }); });
primary.reset(new std::thread([=, this] { primary.reset(new std::thread([=, this] {
@ -34,10 +41,8 @@ public:
Workers.acquire(); Workers.acquire();
th.detach(); th.detach();
} }
for (auto i : std::views::iota(0, Threads)) for (int i : std::views::iota(0, N))
Workers.acquire(); Workers.acquire();
for (auto i : std::views::iota(0, Threads))
Workers.release();
Stop.store(true); Stop.store(true);
})); }));
} }
@ -73,4 +78,5 @@ private:
} }
}; };
#endif // RENDERER_H

@ -10,9 +10,10 @@
#include <tuple> #include <tuple>
enum class Material : int { enum class Material : int {
Lambertian, Lambertian = 0,
Metal, Metal,
Dielectric Dielectric,
Undefined
}; };
struct Sphere struct Sphere

Loading…
Cancel
Save