This commit is contained in:
Gamemaker1998
2025-01-25 15:08:30 +01:00
17 changed files with 246 additions and 138 deletions
-20
View File
@@ -1,20 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/RayTracer",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/",
"environment": [],
"externalConsole": false,
"MIMode": "lldb"
}
]
}
-4
View File
@@ -1,4 +0,0 @@
{
"cmake.buildDirectory": "${workspaceFolder}/bin/",
"cmake.generator": ""
}
+3 -4
View File
@@ -11,6 +11,7 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/external/vcpkg/scripts/buil
project(RayTracer) project(RayTracer)
find_package(Vulkan REQUIRED)
find_package(glew CONFIG REQUIRED) find_package(glew CONFIG REQUIRED)
find_package(assimp CONFIG REQUIRED) find_package(assimp CONFIG REQUIRED)
find_package(glfw3 CONFIG REQUIRED) find_package(glfw3 CONFIG REQUIRED)
@@ -20,14 +21,12 @@ find_package(imgui CONFIG REQUIRED)
add_executable(RayTracer "") add_executable(RayTracer "")
target_include_directories(RayTracer PUBLIC src/) target_include_directories(RayTracer PUBLIC src/)
target_link_libraries(RayTracer PUBLIC Vulkan::Vulkan)
target_link_libraries(RayTracer PUBLIC Vulkan::Headers)
target_link_libraries(RayTracer PUBLIC assimp::assimp) target_link_libraries(RayTracer PUBLIC assimp::assimp)
target_link_libraries(RayTracer PUBLIC glfw) target_link_libraries(RayTracer PUBLIC glfw)
target_link_libraries(RayTracer PUBLIC imgui::imgui) target_link_libraries(RayTracer PUBLIC imgui::imgui)
if(APPLE)
target_link_libraries(RayTracer PUBLIC GLEW::GLEW) target_link_libraries(RayTracer PUBLIC GLEW::GLEW)
else()
target_link_libraries(RayTracer PUBLIC GLEW::glew)
endif()
target_link_libraries(RayTracer PUBLIC glm::glm) target_link_libraries(RayTracer PUBLIC glm::glm)
target_link_libraries(RayTracer PUBLIC KTX::ktx) target_link_libraries(RayTracer PUBLIC KTX::ktx)
+1 -1
View File
View File
+3 -1
View File
@@ -3,8 +3,10 @@ target_sources(RayTracer
main.cpp main.cpp
Minimal.h Minimal.h
ThreadPool.h ThreadPool.h
ThreadPool.cpp) ThreadPool.cpp
)
add_subdirectory(gpu/)
add_subdirectory(scene/) add_subdirectory(scene/)
add_subdirectory(window/) add_subdirectory(window/)
add_subdirectory(util/) add_subdirectory(util/)
+16 -3
View File
@@ -1,9 +1,22 @@
#pragma once #pragma once
#include <coroutine>
#include <memory> #include <memory>
#define DEFINE_REF(x) \ #define DEFINE_REF(x) typedef ::std::unique_ptr<x> P##x;
typedef ::std::unique_ptr<x> P##x; \
#define DECLARE_REF(x) \ #define DECLARE_REF(x) \
class x; \ class x; \
typedef ::std::unique_ptr<x> P##x; \ typedef ::std::unique_ptr<x> P##x;
struct Task
{
struct promise_type
{
Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
std::coroutine_handle<promise_type> handle;
};
+6 -4
View File
@@ -26,8 +26,9 @@ void ThreadPool::runBatch(Batch&& batch)
{ {
{ {
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
numRemaining = batch.jobs.size();
taskQueue.push_back(batch); taskQueue.push_back(batch);
queueCV.notify_one(); queueCV.notify_all();
} }
while (true) while (true)
{ {
@@ -42,7 +43,7 @@ void ThreadPool::work()
{ {
while (running) while (running)
{ {
std::function<void()> job; Task job;
{ {
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
if (taskQueue.empty() || taskQueue.front().jobs.empty()) if (taskQueue.empty() || taskQueue.front().jobs.empty())
@@ -53,10 +54,11 @@ void ThreadPool::work()
job = taskQueue.front().jobs.front(); job = taskQueue.front().jobs.front();
taskQueue.front().jobs.pop_front(); taskQueue.front().jobs.pop_front();
} }
job(); job.handle();
{ {
std::unique_lock l(queueLock); std::unique_lock l(queueLock);
if (taskQueue.front().jobs.empty()) numRemaining--;
if (numRemaining == 0)
{ {
taskQueue.pop_front(); taskQueue.pop_front();
completedCV.notify_one(); completedCV.notify_one();
+3 -1
View File
@@ -3,10 +3,11 @@
#include <functional> #include <functional>
#include <list> #include <list>
#include <thread> #include <thread>
#include "Minimal.h"
struct Batch struct Batch
{ {
std::list<std::function<void()>> jobs; std::list<Task> jobs;
}; };
class ThreadPool class ThreadPool
@@ -21,6 +22,7 @@ private:
std::mutex queueLock; std::mutex queueLock;
std::condition_variable queueCV; std::condition_variable queueCV;
std::condition_variable completedCV; std::condition_variable completedCV;
uint32_t numRemaining;
std::list<Batch> taskQueue; std::list<Batch> taskQueue;
std::vector<std::thread> workers; std::vector<std::thread> workers;
}; };
+4
View File
@@ -0,0 +1,4 @@
target_sources(RayTracer
PRIVATE
Renderer.h
Renderer.cpp)
+72
View File
@@ -0,0 +1,72 @@
#include "Renderer.h"
Renderer::Renderer()
: instance(nullptr), physicalDevice(nullptr), device(nullptr), queue(nullptr), cmdPool(nullptr), cmdBuffers(nullptr),
descriptorLayout(nullptr), descriptorSet(nullptr), descriptorPool(nullptr), pipelineLayout(nullptr), rayGen(nullptr),
closestHit(nullptr), miss(nullptr), pipeline(nullptr)
{
vk::RayTracingPipelineCreateInfoKHR pipelineCreateInfo(0, );
}
Renderer::~Renderer() {}
void Renderer::createDevice() {
vk::ApplicationInfo appInfo("RayTracer", 1, "RayTracer", 1, VK_API_VERSION_1_3);
vk::InstanceCreateInfo instanceCreateInfo({}, &appInfo);
instance = Instance(context, instanceCreateInfo);
auto physicalDevices = PhysicalDevices(instance);
for (auto& dev : physicalDevices)
{
for (auto ext : dev.enumerateDeviceExtensionProperties())
{
if (std::strcmp(ext.extensionName, vk::KHRRayTracingPipelineExtensionName))
{
physicalDevice = dev;
break;
}
}
}
uint32_t computeQueueFamily = 0;
auto queueProps = physicalDevice.getQueueFamilyProperties();
for (uint32_t i = 0; i < queueProps.size(); ++i)
{
if (queueProps[i].queueFlags & vk::QueueFlagBits::eCompute)
{
computeQueueFamily = i;
break;
}
}
float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo({}, computeQueueFamily, 1, &queuePriority);
vk::DeviceCreateInfo deviceCreateInfo({}, deviceQueueCreateInfo);
device = Device(physicalDevice, deviceCreateInfo);
}
void Renderer::createCommands()
{
vk::CommandPoolCreateInfo commandPoolCreateInfo({}, computeQueueFamily);
cmdPool = CommandPool(device, commandPoolCreateInfo);
// allocate a CommandBuffer from the CommandPool
vk::CommandBufferAllocateInfo commandBufferAllocateInfo(cmdPool, vk::CommandBufferLevel::ePrimary, 10);
cmdBuffers = vk::raii::CommandBuffers(device, commandBufferAllocateInfo);
}
void Renderer::createDescriptors() {
vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex);
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo({}, descriptorSetLayoutBinding);
descriptorLayout = DescriptorSetLayout(device, descriptorSetLayoutCreateInfo);
// create a PipelineLayout using that DescriptorSetLayout
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, *descriptorLayout);
pipelineLayout = PipelineLayout(device, pipelineLayoutCreateInfo);
}
void Renderer::createShaders() {
}
void Renderer::render(Camera cam, RenderParameter param) {}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include "scene/Scene.h"
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_raii.hpp>
using namespace vk::raii;
struct Renderer : public Scene
{
public:
Renderer();
virtual ~Renderer();
private:
void createDevice();
void createCommands();
void createDescriptors();
void createShaders();
Context context;
Instance instance;
PhysicalDevice physicalDevice;
Device device;
Queue queue;
uint32_t computeQueueFamily;
CommandPool cmdPool;
CommandBuffers cmdBuffers;
DescriptorSetLayout descriptorLayout;
DescriptorSet descriptorSet;
DescriptorPool descriptorPool;
PipelineLayout pipelineLayout;
ShaderModule rayGen;
ShaderModule closestHit;
ShaderModule miss;
Pipeline pipeline;
virtual void render(Camera cam, RenderParameter param);
};
+4 -4
View File
@@ -8,15 +8,15 @@
int main() int main()
{ {
Scene scene; Scene scene;
Window window(800, 600); Window window(1920, 1080);
scene.render( scene.startRender(
Camera{ Camera{
.position = glm::vec3(10, 0, 0), .position = glm::vec3(10, 0, 0),
.direction = glm::vec3(-1, 0, 0), .direction = glm::vec3(-1, 0, 0),
}, },
RenderParameter{ RenderParameter{
.width = 800, .width = 1920,
.height = 600, .height = 1080,
.numSamples = 10000, .numSamples = 10000,
}); });
while (true) while (true)
+18 -23
View File
@@ -1,22 +1,20 @@
#include "Scene.h" #include "Scene.h"
#include "util/ModelLoader.h" #include "util/ModelLoader.h"
#include <iostream>
#include <chrono> #include <chrono>
#include <iostream>
Scene::Scene() Scene::Scene()
{ {
bvh.addModels(ModelLoader::loadModel("../cube.fbx"), bvh.addModels(ModelLoader::loadModel("../res/models/cube.fbx"),
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 4.0f, 0.0f)));
bvh.generate(); bvh.generate();
} }
Scene::~Scene() {} Scene::~Scene() {}
static bool firstTime = true; static bool firstTime = true;
void Scene::render(Camera cam, RenderParameter params) void Scene::startRender(Camera cam, RenderParameter params)
{ {
if (!firstTime) if (!firstTime)
{ {
@@ -29,8 +27,10 @@ void Scene::render(Camera cam, RenderParameter params)
accumulator.clear(); accumulator.clear();
image.resize(params.width * params.height); image.resize(params.width * params.height);
accumulator.resize(params.width * params.height); accumulator.resize(params.width * params.height);
worker = std::thread( worker = std::thread(&Scene::render, this, cam, params);
[&, cam, params]() }
void Scene::render(Camera cam, RenderParameter params)
{ {
for (int samp = 0; samp < params.numSamples; ++samp) for (int samp = 0; samp < params.numSamples; ++samp)
{ {
@@ -40,24 +40,20 @@ void Scene::render(Camera cam, RenderParameter params)
for (int w = 0; w < params.width; ++w) for (int w = 0; w < params.width; ++w)
{ {
batch.jobs.push_back( batch.jobs.push_back(
[&, w]() [&](int w) -> Task
{ {
for (int h = 0; h < params.height; ++h) for (int h = 0; h < params.height; ++h)
{ {
Ray r = Ray{ Ray r = Ray{.origin = glm::vec3(0.0f),
.origin = glm::vec3(0.0f), .direction = glm::normalize(
.direction = glm::normalize(glm::vec3((float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX)) glm::vec3((float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX))};
}; bvh.traceRay(r);
auto intersectionInfo = bvh.traceRay(r); accumulator[w + h * params.width] +=
glm::vec3(w / float(params.width * params.numSamples), h / float(params.height * params.numSamples), 0);
if(intersectionInfo.has_value())
{
accumulator[w + h * params.width] += intersectionInfo->albedo;
//glm::vec3(w / float(params.width * params.numSamples), h / float(params.height * params.numSamples), 0);
} }
} co_return;
}); }(w));
} }
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
threadPool.runBatch(std::move(batch)); threadPool.runBatch(std::move(batch));
@@ -65,5 +61,4 @@ void Scene::render(Camera cam, RenderParameter params)
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << std::endl; std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << std::endl;
std::memcpy(image.data(), accumulator.data(), accumulator.size() * sizeof(glm::vec3)); std::memcpy(image.data(), accumulator.data(), accumulator.size() * sizeof(glm::vec3));
} }
});
} }
+3 -2
View File
@@ -15,10 +15,11 @@ class Scene
{ {
public: public:
Scene(); Scene();
~Scene(); virtual ~Scene();
void render(Camera cam, RenderParameter params); void startRender(Camera cam, RenderParameter params);
constexpr const std::vector<glm::vec3>& getImage() const { return image; } constexpr const std::vector<glm::vec3>& getImage() const { return image; }
private: private:
virtual void render(Camera cam, RenderParameter params);
std::atomic_bool pendingCancel = false; std::atomic_bool pendingCancel = false;
ThreadPool threadPool; ThreadPool threadPool;
std::thread worker; std::thread worker;
+1 -1
View File
@@ -4,12 +4,12 @@
"name": "imgui", "name": "imgui",
"features": [ "glfw-binding", "opengl3-binding" ] "features": [ "glfw-binding", "opengl3-binding" ]
}, },
"vulkan",
"assimp", "assimp",
"ktx", "ktx",
"glfw3", "glfw3",
"glew", "glew",
"glm", "glm",
"stb",
"fmt" "fmt"
] ]
} }