-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/add vulkan device #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
adc2e89
8177c35
696dba7
b99d7c8
4447563
980201f
ec91556
b1a232c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| #include "vulkandevice.h" | ||
|
|
||
| namespace segfault::renderer { | ||
|
|
||
| bool QueueFamilyIndices::isGraphicsComplete() const { | ||
| return graphicsFamily.has_value() && presentFamily.has_value(); | ||
| } | ||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Prompt for AI Agents |
||
|
|
||
| VulkanDevice::VulkanDevice(VkPhysicalDevice physicalDevice) : mPhysicalDevice(physicalDevice) { | ||
| // empty | ||
| } | ||
|
|
||
| VulkanDevice::~VulkanDevice() { | ||
| shutdown(); | ||
| } | ||
|
|
||
| bool VulkanDevice::init(VkSurfaceKHR surface, const DeviceRequirements& requirements) { | ||
| if (mDevice != VK_NULL_HANDLE) { | ||
| return true; // Already initialized | ||
| } | ||
|
|
||
| mSurface = surface; | ||
|
|
||
| return true; | ||
| } | ||
|
Comment on lines
+13
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lifecycle contract is incomplete: destructor is empty and
🧰 Tools🪛 GitHub Check: SonarCloud Code Analysis[failure] 13-13: Use "=default" instead of the default implementation of this special member functions. 🤖 Prompt for AI Agents |
||
|
|
||
| void VulkanDevice::shutdown() { | ||
| if (mDevice == VK_NULL_HANDLE) { | ||
| return; | ||
| } | ||
|
|
||
| vkDestroyDevice(mDevice, nullptr); | ||
| mDevice = VK_NULL_HANDLE; | ||
| mSurface = VK_NULL_HANDLE; | ||
| } | ||
|
|
||
| VulkanBuffer* VulkanDevice::createBuffer(size_t size, BufferUsage usageFlags, uint32_t memoryPropertyFlags) { | ||
| VulkanBuffer* buffer = new VulkanBuffer(mPhysicalDevice, mDevice); | ||
|
Check failure on line 38 in src/runtime/renderer/vulkandevice.cpp
|
||
| if (!buffer->init(size, usageFlags, memoryPropertyFlags)) { | ||
| delete buffer; | ||
|
Check failure on line 40 in src/runtime/renderer/vulkandevice.cpp
|
||
| return nullptr; | ||
| } | ||
| return buffer; | ||
| } | ||
|
|
||
| bool VulkanDevice::copyBuffer(VulkanBuffer* source, VulkanBuffer* destination, VkDeviceSize size, VkQueue queue, VkCommandPool pool) { | ||
| if (!source || !destination) { | ||
| return false; | ||
| } | ||
|
|
||
| VkCommandBuffer copyCmd = createCommandBuffer(pool); | ||
| VkBufferCopy bufferCopy{}; | ||
| if (size == 0) | ||
| { | ||
| bufferCopy.size = source->getSize(); | ||
| } | ||
| else | ||
| { | ||
| bufferCopy.size = size; | ||
| } | ||
|
|
||
| vkCmdCopyBuffer(copyCmd, source->getBuffer(), destination->getBuffer(), 1, &bufferCopy); | ||
|
|
||
| flushCommandBuffer(copyCmd, queue, pool, true); | ||
| } | ||
|
|
||
| VkCommandBuffer VulkanDevice::createCommandBuffer(VkCommandPool commandPool, VkCommandBufferLevel level) { | ||
| VkCommandBufferAllocateInfo allocInfo{}; | ||
| allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; | ||
| allocInfo.commandPool = commandPool; | ||
| allocInfo.level = level; | ||
| allocInfo.commandBufferCount = 1; | ||
|
|
||
| VkCommandBuffer commandBuffer; | ||
|
|
||
| vkAllocateCommandBuffers(mDevice, &allocInfo, &commandBuffer); | ||
| return commandBuffer; | ||
| } | ||
|
|
||
|
|
||
| void VulkanDevice::flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, VkCommandPool pool, bool free) { | ||
| VkSubmitInfo submitInfo{}; | ||
| submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | ||
| submitInfo.commandBufferCount = 1; | ||
| submitInfo.pCommandBuffers = &commandBuffer; | ||
| vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); | ||
| if (free) { | ||
| vkFreeCommandBuffers(mDevice, pool, 1, &commandBuffer); | ||
| } | ||
| } | ||
|
|
||
| } // namespace segfault::renderer | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| #pragma once | ||
|
|
||
| #include "volk.h" | ||
| #include "core/segfault.h" | ||
| #include <vector> | ||
| #include <optional> | ||
| #include <string> | ||
| #include <cstdint> | ||
| #include "vulkantypes.h" | ||
| #include "vulkanbuffer.h" | ||
|
|
||
| namespace segfault::renderer { | ||
|
|
||
| struct QueueFamilyIndices { | ||
| std::optional<uint32_t> graphicsFamily; | ||
| std::optional<uint32_t> presentFamily; | ||
| std::optional<uint32_t> computeFamily; | ||
| std::optional<uint32_t> transferFamily; | ||
|
|
||
| bool isComplete() const; | ||
| bool isGraphicsComplete() const; | ||
| }; | ||
|
|
||
| struct DeviceRequirements { | ||
| std::vector<const char*> requiredExtensions; | ||
| std::vector<const char*> optionalExtensions; | ||
| VkPhysicalDeviceFeatures requiredFeatures{}; | ||
| VkPhysicalDeviceFeatures optionalFeatures{}; | ||
| bool requirePresentQueue{ false }; | ||
| bool requireComputeQueue{ false }; | ||
| bool requireTransferQueue{ false }; | ||
| }; | ||
|
|
||
| struct DeviceProperties { | ||
| VkPhysicalDeviceProperties properties{}; | ||
| VkPhysicalDeviceFeatures features{}; | ||
| VkPhysicalDeviceMemoryProperties memoryProperties{}; | ||
| std::vector<VkExtensionProperties> availableExtensions; | ||
| std::vector<VkQueueFamilyProperties> queueFamilies; | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------------------------- | ||
| /// @class VulkanDevice | ||
| /// @brief Encapsulates a Vulkan physical and logical device with queue management. | ||
| /// | ||
| /// This class manages the selection, creation, and lifecycle of Vulkan devices. | ||
| /// It provides access to device properties, features, queues, and memory management. | ||
| //--------------------------------------------------------------------------------------------- | ||
| class SEGFAULT_EXPORT VulkanDevice final { | ||
| public: | ||
| // Disallow copying | ||
| VulkanDevice(const VulkanDevice&) = delete; | ||
| VulkanDevice& operator=(const VulkanDevice&) = delete; | ||
|
|
||
| /// @brief Constructs a VulkanDevice. | ||
| /// @param instance The Vulkan instance. | ||
| VulkanDevice(VkPhysicalDevice physicalDevice); | ||
|
Check failure on line 57 in src/runtime/renderer/vulkandevice.h
|
||
|
Comment on lines
+1
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Header docs/compliance need cleanup (MIT header + incorrect Doxygen param). MIT file header is missing, and Line 54 documents 🧰 Tools🪛 GitHub Check: SonarCloud Code Analysis[failure] 55-55: Add the "explicit" keyword to this constructor. 🤖 Prompt for AI AgentsSource: Coding guidelines There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make the single-argument constructor Implicit conversion from 🧰 Tools🪛 GitHub Check: SonarCloud Code Analysis[failure] 55-55: Add the "explicit" keyword to this constructor. 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
|
|
||
| /// @brief The class destructor. Ensures that all Vulkan resources are properly released. | ||
| ~VulkanDevice(); | ||
|
|
||
| /// @brief Initializes the device with the given surface and requirements. | ||
| /// @param surface The presentation surface (can be VK_NULL_HANDLE for headless). | ||
| /// @param requirements Device feature and extension requirements. | ||
| /// @return True if device initialization succeeded. | ||
| bool init(VkSurfaceKHR surface, const DeviceRequirements& requirements = {}); | ||
|
|
||
| /// @brief Shuts down the device and releases all resources. | ||
| void shutdown(); | ||
|
|
||
| // Accessors | ||
| VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; } | ||
| VkDevice getDevice() const { return mDevice; } | ||
| VkQueue getGraphicsQueue() const { return mGraphicsQueue; } | ||
| VkQueue getPresentQueue() const { return mPresentQueue; } | ||
| const QueueFamilyIndices& getQueueFamilyIndices() const { return mQueueFamilyIndices; } | ||
| uint32_t getGraphicsQueueFamilyIndex() const; | ||
| uint32_t getPresentQueueFamilyIndex() const; | ||
| const DeviceProperties& getProperties() const { return mProperties; } | ||
| VulkanBuffer* createBuffer(size_t size, BufferUsage usageFlags, uint32_t memoryPropertyFlags); | ||
| bool copyBuffer(VulkanBuffer *source, VulkanBuffer *destination, VkDeviceSize size, VkQueue queue, VkCommandPool pool); | ||
| VkCommandBuffer createCommandBuffer(VkCommandPool commandPool, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY); | ||
| void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, VkCommandPool pool, bool free); | ||
|
|
||
| private: | ||
| VkPhysicalDevice mPhysicalDevice{}; | ||
| VkDevice mDevice{}; | ||
| VkQueue mGraphicsQueue{}; | ||
| VkQueue mPresentQueue{}; | ||
| QueueFamilyIndices mQueueFamilyIndices{}; | ||
| DeviceProperties mProperties{}; | ||
| VkSurfaceKHR mSurface{}; | ||
| }; | ||
|
|
||
| } // namespace segfault::renderer | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #pragma once | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing required MIT license header in new source file. Line 1 starts directly with 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
| #include <cstdint> | ||
|
|
||
| namespace segfault::renderer { | ||
|
|
||
| enum class BufferUsage : uint32_t { | ||
| VertexBuffer = 0x1, | ||
| IndexBuffer = 0x2, | ||
| UniformBuffer = 0x4 | ||
| }; | ||
|
Comment on lines
+7
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Prompt for AI Agents |
||
|
|
||
| } // namespace segfault::renderer | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| #include "vulkanutils.h" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing MIT license header in new This source file should include the required MIT license header at the top. 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| #include "core/segfaultexception.h" | ||
| #include "volk.h" | ||
|
|
||
| #include <array> | ||
|
|
||
| namespace segfault::renderer { | ||
|
|
||
| using namespace segfault::core; | ||
|
|
||
| std::array<VkVertexInputAttributeDescription, 3> Vertex::getAttributeDescriptions() { | ||
| std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{}; | ||
|
|
||
| attributeDescriptions[0].binding = 0; | ||
| attributeDescriptions[0].location = 0; | ||
| attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; | ||
| attributeDescriptions[0].offset = offsetof(Vertex, pos); | ||
|
|
||
| attributeDescriptions[1].binding = 0; | ||
| attributeDescriptions[1].location = 1; | ||
| attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; | ||
| attributeDescriptions[1].offset = offsetof(Vertex, color); | ||
|
|
||
| attributeDescriptions[2].binding = 0; | ||
| attributeDescriptions[2].location = 2; | ||
| attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; | ||
| attributeDescriptions[2].offset = offsetof(Vertex, texCoord); | ||
|
|
||
| return attributeDescriptions; | ||
| } | ||
|
|
||
| VkVertexInputBindingDescription Vertex::getBindingDescription() { | ||
| VkVertexInputBindingDescription bindingDescription{}; | ||
|
|
||
| bindingDescription.binding = 0; | ||
| bindingDescription.stride = sizeof(Vertex); | ||
| bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; | ||
|
|
||
| return bindingDescription; | ||
| } | ||
|
|
||
| VkFormat VulkanUtils::findSupportedFormat(VkPhysicalDevice &physicalDevice, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { | ||
| for (VkFormat format : candidates) { | ||
| VkFormatProperties props; | ||
| vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props); | ||
| if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { | ||
| return format; | ||
| } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { | ||
| return format; | ||
| } | ||
| } | ||
|
|
||
| throw SegfaultException("failed to find supported format!"); | ||
| } | ||
|
|
||
| VkFormat VulkanUtils::findDepthFormat(VkPhysicalDevice &physicalDevice) { | ||
| return findSupportedFormat( | ||
| physicalDevice, | ||
| { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT }, | ||
| VK_IMAGE_TILING_OPTIMAL, | ||
| VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | ||
| ); | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing MIT license header in new
.cppfile.Please add the required MIT header block at the top of this file.
As per coding guidelines, "Include MIT license header in all source files".
🤖 Prompt for AI Agents
Source: Coding guidelines