diff --git a/CMakeLists.txt b/CMakeLists.txt index b1f93cd..56f93ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ add_library(unlogic STATIC src/graphic/ugl/Vertex.h src/graphic/Plot.h src/graphic/Plot.cpp + src/graphic/VertexBuffer.h ) target_link_libraries(unlogic PUBLIC ${llvm_libs} glm::glm buffalo) target_include_directories(unlogic PUBLIC ${LLVM_INCLUDE_DIRS} src) @@ -78,6 +79,7 @@ qt_add_executable(unlogic-calculator src/calculator/renderer/VulkanInstance.h src/calculator/renderer/VulkanInstance.cpp src/calculator/renderer/VulkanRenderer.cpp + src/calculator/renderer/VulkanVertexBuffer.h src/calculator/resource/shaders/plot.frag src/calculator/resource/shaders/plot.vert ) diff --git a/src/calculator/Window.h b/src/calculator/Window.h index 7791fe5..fac4a45 100644 --- a/src/calculator/Window.h +++ b/src/calculator/Window.h @@ -14,6 +14,7 @@ #include #include #include "renderer/VulkanInstance.h" +#include "renderer/VulkanVertexBuffer.h" #include "renderer/VulkanWindow.h" namespace ui @@ -40,8 +41,6 @@ namespace ui public: Window() { - this->scene_ = std::make_unique(); - auto body = new QWidget; auto main_layout = new QVBoxLayout; @@ -58,6 +57,8 @@ namespace ui splitter->addWidget(this->editor_); auto render_window = new VulkanWindow; + auto vertex_buffer_provider = std::make_unique(render_window); + this->scene_ = std::make_unique(std::move(vertex_buffer_provider)); render_window->setVulkanInstance(ui::vk_global); render_window->setScene(this->scene_.get()); diff --git a/src/calculator/renderer/VulkanRenderer.cpp b/src/calculator/renderer/VulkanRenderer.cpp index 995e92a..66dc9c7 100644 --- a/src/calculator/renderer/VulkanRenderer.cpp +++ b/src/calculator/renderer/VulkanRenderer.cpp @@ -151,6 +151,14 @@ void VulkanRenderer::initResources() this->createStandardPipeline(this->plot_pipeline_, this->plot_pipeline_layout_, ":/shaders/plot.vert.qsb", ":/shaders/plot.frag.qsb"); this->createStandardPipeline(this->graph_pipeline_, this->graph_pipeline_layout_, ":/shaders/graph.vert.qsb", ":/shaders/graph.frag.qsb"); + + std::array corners = { + glm::vec2 { -1.f, -1.f }, + glm::vec2 { 1.f, -1.f }, + glm::vec2 { 1.f, 1.f }, + glm::vec2 { -1.f, 1.f }, + }; + this->gridlines_ = this->window_->scene->Rect(corners, unlogic::Color::Green); } void VulkanRenderer::releaseResources() @@ -222,7 +230,7 @@ void VulkanRenderer::startNextFrame() // Commence drawing scene if(this->window_->scene->draw_gridlines) { - this->drawGridlines(); + this->drawVertexBuffer(this->gridlines_.get(), this->graph_pipeline_); } this->dev_->vkCmdEndRenderPass(cmd); @@ -269,61 +277,14 @@ VkShaderModule VulkanRenderer::loadShader(std::string_view path) return module; } -void VulkanRenderer::drawGridlines() +void VulkanRenderer::drawVertexBuffer(unlogic::VertexBuffer *vertex_buffer, VkPipeline pipeline) { VkCommandBuffer cmd = this->window_->currentCommandBuffer(); + this->dev_->vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkBuffer buffer; - VkDeviceMemory memory; - - std::array vertices = { - unlogic::Vertex {{ -1.f, -1.f }, unlogic::Color::Green}, - unlogic::Vertex {{ 1.f, -1.f }, unlogic::Color::Green}, - unlogic::Vertex {{ 1.f, 1.f }, unlogic::Color::Green}, - - unlogic::Vertex {{ 1.f, 1.f }, unlogic::Color::Blue}, - unlogic::Vertex {{ -1.f, 1.f }, unlogic::Color::Blue}, - unlogic::Vertex {{ -1.f, -1.f }, unlogic::Color::Blue}, - }; - - VkBufferCreateInfo buffer_info { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = sizeof(unlogic::Vertex) * vertices.size(), - .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - if(this->dev_->vkCreateBuffer(this->window_->device(), &buffer_info, nullptr, &buffer) != VK_SUCCESS) - { - throw std::runtime_error("failed to create buffer"); - } - - VkMemoryAllocateInfo memory_allocate_info { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = buffer_info.size, - .memoryTypeIndex = this->window_->hostVisibleMemoryIndex(), - }; - - if(this->dev_->vkAllocateMemory(this->window_->device(), &memory_allocate_info, nullptr, &memory) != VK_SUCCESS) - { - throw std::runtime_error("failed to allocate memory"); - } - - this->dev_->vkBindBufferMemory(this->window_->device(), buffer, memory, 0); - - void *data = nullptr; - this->dev_->vkMapMemory(this->window_->device(), memory, 0, buffer_info.size, 0, &data); - memcpy(data, vertices.data(), buffer_info.size); - this->dev_->vkUnmapMemory(this->window_->device(), memory); - - this->dev_->vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, this->graph_pipeline_); - - std::array buffers = { buffer }; - std::array offsets = { 0 }; + std::array buffers = { static_cast(vertex_buffer->GetNativeHandle()) }; + constexpr std::array offsets = { 0 }; this->dev_->vkCmdBindVertexBuffers(cmd, 0, 1, buffers.data(), offsets.data()); - this->dev_->vkCmdDraw(cmd, vertices.size(), 1, 0, 0); - - //this->dev_->vkDestroyBuffer(this->window_->device(), buffer, nullptr); - //this->dev_->vkFreeMemory(this->window_->device(), memory, nullptr); + this->dev_->vkCmdDraw(cmd, vertex_buffer->GetVertexCount(), 1, 0, 0); } diff --git a/src/calculator/renderer/VulkanRenderer.h b/src/calculator/renderer/VulkanRenderer.h index fc84302..b29944d 100644 --- a/src/calculator/renderer/VulkanRenderer.h +++ b/src/calculator/renderer/VulkanRenderer.h @@ -3,6 +3,7 @@ #include #include +#include "graphic/VertexBuffer.h" namespace ui { @@ -20,6 +21,8 @@ namespace ui QVulkanDeviceFunctions *dev_ = nullptr; + std::unique_ptr gridlines_ = nullptr; + public: // Vulkan Utils VkShaderModule loadShader(std::string_view path); @@ -31,7 +34,7 @@ namespace ui void startNextFrame() override; // Draw Commands - void drawGridlines(); + void drawVertexBuffer(unlogic::VertexBuffer *vertex_buffer, VkPipeline pipeline); VulkanRenderer(VulkanWindow *window) : window_(window) {} }; diff --git a/src/calculator/renderer/VulkanVertexBuffer.h b/src/calculator/renderer/VulkanVertexBuffer.h new file mode 100644 index 0000000..a226650 --- /dev/null +++ b/src/calculator/renderer/VulkanVertexBuffer.h @@ -0,0 +1,104 @@ +// +// Created by Nathan on 11/21/2024. +// + +#ifndef VULKANVERTEXBUFFER_H +#define VULKANVERTEXBUFFER_H + +#include +#include +#include "graphic/VertexBuffer.h" + +namespace unlogic +{ + class VulkanVertexBuffer : public VertexBuffer + { + QVulkanWindow *window_ = nullptr; + QVulkanDeviceFunctions *dev_ = nullptr; + + VkBuffer vk_buffer_ = nullptr; + VkDeviceMemory vk_memory_ = nullptr; + + public: + void Release() override + { + if(this->vk_buffer_) + { + this->dev_->vkDestroyBuffer(this->window_->device(), this->vk_buffer_, nullptr); + this->vk_buffer_ = nullptr; + } + + if(this->vk_memory_) + { + this->dev_->vkFreeMemory(this->window_->device(), this->vk_memory_, nullptr); + this->vk_memory_ = nullptr; + } + } + + void Allocate(Vertex const *vertices, std::size_t vertex_count) override + { + this->Release(); + this->SetVertexCount(vertex_count); + + VkBufferCreateInfo buffer_info { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = sizeof(Vertex) * vertex_count, + .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + + if(this->dev_->vkCreateBuffer(this->window_->device(), &buffer_info, nullptr, &this->vk_buffer_) != VK_SUCCESS) + { + throw std::runtime_error("failed to create buffer"); + } + + VkMemoryAllocateInfo memory_allocate_info { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = buffer_info.size, + .memoryTypeIndex = this->window_->hostVisibleMemoryIndex(), + }; + + if(this->dev_->vkAllocateMemory(this->window_->device(), &memory_allocate_info, nullptr, &this->vk_memory_) != VK_SUCCESS) + { + throw std::runtime_error("failed to allocate memory"); + } + + this->dev_->vkBindBufferMemory(this->window_->device(), this->vk_buffer_, this->vk_memory_, 0); + + void *data = nullptr; + this->dev_->vkMapMemory(this->window_->device(), this->vk_memory_, 0, buffer_info.size, 0, &data); + memcpy(data, vertices, buffer_info.size); + this->dev_->vkUnmapMemory(this->window_->device(), this->vk_memory_); + } + + void *GetNativeHandle() override + { + return (void*)this->vk_buffer_; + } + + VulkanVertexBuffer(QVulkanWindow *window) : window_(window) + { + this->dev_ = this->window_->vulkanInstance()->deviceFunctions(this->window_->device()); + } + + ~VulkanVertexBuffer() override + { + this->VulkanVertexBuffer::Release(); + } + }; + + class VulkanVertexBufferProvider : public VertexBufferProvider + { + QVulkanWindow *window_ = nullptr; + + public: + std::unique_ptr GetVertexBuffer() override + { + return std::make_unique(this->window_); + } + + VulkanVertexBufferProvider(QVulkanWindow *window) : window_(window) {} + }; +} + +#endif //VULKANVERTEXBUFFER_H diff --git a/src/graphic/Graph.cpp b/src/graphic/Graph.cpp deleted file mode 100644 index a707f28..0000000 --- a/src/graphic/Graph.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include "graphic/ugl/Canvas.h" -#include "graphic/Graph.h" - -void unlogic::Graph::DrawOnto(unlogic::Canvas &canvas) -{ - auto world_bounds = canvas.GetWorldBounds(); - - // x, y gridlines - float gridline_thickness = this->axis_thickness_; - float gray_intensity = 0.93f; - for(int x = std::floor(world_bounds.x); x < std::ceil(world_bounds.z); x++) - { - Line gridline({(float)x, world_bounds.y}, {(float)x, world_bounds.w}); - gridline.SetLineThickness(gridline_thickness); - gridline.SetColor({gray_intensity, gray_intensity, gray_intensity, 1.f}); - gridline.DrawOnto(canvas); - } - - for(int y = std::floor(world_bounds.w); y < std::ceil(world_bounds.y); y++) - { - Line gridline({world_bounds.x, (float)y}, {world_bounds.z, (float)y}); - gridline.SetLineThickness(gridline_thickness); - gridline.SetColor({gray_intensity, gray_intensity, gray_intensity, 1.f}); - gridline.DrawOnto(canvas); - } - - // Draw x, y axis - Line x_axis({world_bounds.x, 0.f}, {world_bounds.z, 0.f}); - x_axis.SetLineThickness(this->axis_thickness_); - x_axis.SetColor({0.f, 0.f, 0.f, 1.f}); - x_axis.DrawOnto(canvas); - - Line y_axis({0.f, world_bounds.y}, {0.f, world_bounds.w}); - y_axis.SetLineThickness(this->axis_thickness_); - y_axis.SetColor({0.f, 0.f, 0.f, 1.f}); - y_axis.DrawOnto(canvas); - - // Draw plots - for(auto &plot : this->plots_) - { - plot.DrawOnto(canvas); - } -} diff --git a/src/graphic/Graph.h b/src/graphic/Graph.h deleted file mode 100644 index 1a36cc3..0000000 --- a/src/graphic/Graph.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Created by nathan on 5/27/24. -// - -#ifndef UNLOGIC_GRAPH_H -#define UNLOGIC_GRAPH_H - -#include -#include -#include -#include "compiler/Compiler.h" -#include "graphic/ugl/Drawable.h" -#include "graphic/ugl/shapes/Line.h" - -namespace unlogic -{ - class Graph : public Drawable - { - std::vector plots_; - glm::vec2 domain_; - float axis_thickness_ = 0.1f; - - public: - void DrawOnto(Canvas &canvas) override; - - std::vector &GetLines() - { - return this->plots_; - } - - void AddPlot(std::string const &function) - { - //this->plots_.emplace_back(this->compiler_.CompileFunction(function), this->domain_); - } - - Graph(std::initializer_list functions, glm::vec2 domain = {-100.0, 100.0}) : domain_(domain) - { - for(auto const &function : functions) - { - this->AddPlot(function); - } - } - - Graph(std::string const &function, glm::vec2 domain = {-100.0, 100.0}) : Graph(std::initializer_list{function}, domain) {} - - Graph(glm::vec2 domain = {-100.0, 100.0}) : domain_(domain) {}; - }; -} - -#endif //UNLOGIC_GRAPH_H diff --git a/src/graphic/Plot.cpp b/src/graphic/Plot.cpp index b7ada36..d44b5ea 100644 --- a/src/graphic/Plot.cpp +++ b/src/graphic/Plot.cpp @@ -2,6 +2,7 @@ // Created by Nathan on 11/14/2024. // #include +#include #include "Plot.h" #include "ugl/Vertex.h" @@ -21,6 +22,7 @@ Plot2d::Plot2d(std::string name, Plot2dFunctionType fn) : name_(std::move(name)) points.emplace_back(x, y); } + /* this->line_.vertices.clear(); this->line_.vertices.reserve(points.size() * 2); double dx = 0.0; @@ -44,4 +46,5 @@ Plot2d::Plot2d(std::string name, Plot2dFunctionType fn) : name_(std::move(name)) this->line_.vertices.push_back({glm::vec2(point.x + tx, point.y - ty), this->color_}); // a1 this->line_.vertices.push_back({glm::vec2(point.x - tx, point.y + ty), this->color_}); // a2 } + */ } diff --git a/src/graphic/Plot.h b/src/graphic/Plot.h index 5cb4164..db41e96 100644 --- a/src/graphic/Plot.h +++ b/src/graphic/Plot.h @@ -7,7 +7,6 @@ #include #include -#include "ugl/shapes/Line.h" #include "Color.h" namespace unlogic @@ -27,7 +26,7 @@ namespace unlogic float precision_ = 0.1f; float line_thickness_ = 10.f; - Line line_; + //Line line_; Plot2d(std::string name, Plot2dFunctionType fn); diff --git a/src/graphic/Scene.h b/src/graphic/Scene.h index 8103abc..62f017d 100644 --- a/src/graphic/Scene.h +++ b/src/graphic/Scene.h @@ -5,14 +5,47 @@ #ifndef SCENE_H #define SCENE_H +#include +#include +#include +#include "VertexBuffer.h" #include "Color.h" namespace unlogic { struct Scene { + std::unique_ptr vertex_buffer_provider; + Color background = Color::White; bool draw_gridlines = true; + + std::vector> drawables; + + std::unique_ptr Rect(std::array const &corners, Color color = Color::White) + { + auto vertex_buffer = this->vertex_buffer_provider->GetVertexBuffer(); + + std::array vertices = { + Vertex { corners[0], color }, + Vertex { corners[1], color }, + Vertex { corners[2], color }, + Vertex { corners[2], color }, + Vertex { corners[3], color }, + Vertex { corners[0], color }, + }; + + vertex_buffer->Allocate(vertices.data(), vertices.size()); + + return std::move(vertex_buffer); + } + + Scene() = delete; + + Scene(std::unique_ptr vertex_buffer_provider) : vertex_buffer_provider(std::move(vertex_buffer_provider)) + { + + } }; } // unlogic diff --git a/src/graphic/VertexBuffer.h b/src/graphic/VertexBuffer.h new file mode 100644 index 0000000..6e74b10 --- /dev/null +++ b/src/graphic/VertexBuffer.h @@ -0,0 +1,44 @@ +// +// Created by Nathan on 11/21/2024. +// + +#ifndef VERTEXBUFFER_H +#define VERTEXBUFFER_H + +#include +#include "ugl/Vertex.h" + +namespace unlogic +{ + class VertexBuffer + { + std::size_t vertex_count_ = 0; + + public: + void SetVertexCount(std::size_t vertex_count) + { + this->vertex_count_ = vertex_count; + } + + [[nodiscard]] std::size_t GetVertexCount() const + { + return this->vertex_count_; + } + + virtual void Release() = 0; + virtual void Allocate(Vertex const *vertices, std::size_t vertex_count) = 0; + virtual void *GetNativeHandle() = 0; + + virtual ~VertexBuffer() = default; + }; + + class VertexBufferProvider + { + public: + virtual std::unique_ptr GetVertexBuffer() = 0; + + virtual ~VertexBufferProvider() = default; + }; +} + +#endif //VERTEXBUFFER_H diff --git a/src/graphic/ugl/Drawable.h b/src/graphic/ugl/Drawable.h index a179a94..f405f38 100644 --- a/src/graphic/ugl/Drawable.h +++ b/src/graphic/ugl/Drawable.h @@ -3,8 +3,6 @@ #include #include -#include -#include "graphic/ugl/VertexBuffer.h" namespace unlogic { @@ -16,36 +14,6 @@ namespace unlogic public: virtual void DrawOnto(Canvas &canvas) = 0; }; - - class Shape : public Drawable - { - std::shared_ptr vbo_; - - protected: - glm::vec4 color_ = {1.f, 0.f, 0.f, 1.f}; - float line_thickness_= 0.1f; - float precision_ = 0.1f; - - [[nodiscard]] virtual std::shared_ptr GenerateVertexBuffer() const = 0; - - void Update(); - - public: - void SetColor(glm::vec4 const &color); - - void SetLineThickness(float thickness); - - void SetPrecision(float precision); - - VertexBuffer const &GetVertexBuffer() - { - return *this->vbo_; - } - - void DrawOnto(Canvas &canvas) override; - - virtual ~Shape() = default; - }; } #endif //UNLOGIC_DRAWABLE_H diff --git a/src/graphic/ugl/shapes/Line.h b/src/graphic/ugl/shapes/Line.h deleted file mode 100644 index 628c5cc..0000000 --- a/src/graphic/ugl/shapes/Line.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef UNLOGIC_LINE_H -#define UNLOGIC_LINE_H - -#include -#include "graphic/ugl/Vertex.h" - -namespace unlogic -{ - struct Line - { - std::vector vertices; - }; -} - -#endif //UNLOGIC_LINE_H