Add "copy_memory"

This commit is contained in:
Jiga228
2025-10-04 18:34:20 +07:00
parent 86dfc28a6c
commit 3fbc8f09c0
2 changed files with 178 additions and 41 deletions
+166 -34
View File
@@ -66,12 +66,6 @@ std::vector<const char*> RenderEngine::get_required_extensions()
return extensions; return extensions;
} }
bool RenderEngine::QueueFamilyIndices::is_complete() const
{
return graphics_family.has_value() && present_family.has_value();
}
VkVertexInputBindingDescription RenderEngine::Vertex::get_binding_description() VkVertexInputBindingDescription RenderEngine::Vertex::get_binding_description()
{ {
VkVertexInputBindingDescription description; VkVertexInputBindingDescription description;
@@ -103,9 +97,13 @@ bool RenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surf
vkGetPhysicalDeviceProperties(device, &device_properties); vkGetPhysicalDeviceProperties(device, &device_properties);
vkGetPhysicalDeviceFeatures(device, &device_features); vkGetPhysicalDeviceFeatures(device, &device_features);
try {
QueueFamilyIndices indices = find_queue_family_indices(device, surface); QueueFamilyIndices indices = find_queue_family_indices(device, surface);
} catch (...) {
return false;
}
return indices.is_complete() && check_device_extensions_support(device); return check_device_extensions_support(device);
} }
bool RenderEngine::check_device_extensions_support(VkPhysicalDevice device) bool RenderEngine::check_device_extensions_support(VkPhysicalDevice device)
@@ -141,19 +139,50 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi
std::vector<VkQueueFamilyProperties> family_properties(queueFamilyCount); std::vector<VkQueueFamilyProperties> family_properties(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, family_properties.data()); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, family_properties.data());
// Find graphics
for(uint32_t i = 0; i < family_properties.size(); ++i) for(uint32_t i = 0; i < family_properties.size(); ++i)
{ {
if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
queue_family_indices.graphics_family = i; queue_family_indices.graphics_family = i;
VkBool32 present_support = false;
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support));
if (present_support)
queue_family_indices.present_family = i;
if(queue_family_indices.is_complete())
break; break;
} }
}
if (queue_family_indices.graphics_family.has_value() == false)
throw std::runtime_error("Failed to find a graphics queue family");
// Find present
VkBool32 present_support = false;
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family.value(), surface, &present_support));
if (present_support == VK_TRUE)
queue_family_indices.present_family = queue_family_indices.graphics_family;
else
{
for(uint32_t i = 0; i < family_properties.size(); ++i)
{
present_support = false;
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support));
if (present_support == VK_TRUE)
{
queue_family_indices.present_family = i;
break;
}
}
}
if (queue_family_indices.present_family.has_value() == false)
throw std::runtime_error("Failed to find a present queue family");
for(uint32_t i = 0; i < family_properties.size(); ++i)
{
if (i == queue_family_indices.graphics_family.value())
continue;
if (family_properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT)
queue_family_indices.transfer_family = i;
}
if (queue_family_indices.transfer_family.has_value() == false)
queue_family_indices.transfer_family = queue_family_indices.graphics_family;
return queue_family_indices; return queue_family_indices;
} }
@@ -206,6 +235,43 @@ VkShaderModule RenderEngine::create_shader_module(const std::string& code) const
return shader_module; return shader_module;
} }
void RenderEngine::create_buffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkBuffer* buffer, const std::vector<uint32_t>& queue_families)
{
VkBufferCreateInfo buffer_info{};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = usage;
if (queue_families.size() > 1)
{
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
buffer_info.queueFamilyIndexCount = static_cast<uint32_t>(queue_families.size());
buffer_info.pQueueFamilyIndices = queue_families.data();
}
else
{
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
buffer_info.queueFamilyIndexCount = 0;
buffer_info.pQueueFamilyIndices = nullptr;
}
VK_CHECK(vkCreateBuffer(device_, &buffer_info, nullptr, buffer));
}
void RenderEngine::allocate_memory(VkBuffer buffer, VkMemoryPropertyFlags property, VkDeviceMemory* device_memory)
{
VkMemoryRequirements requirements{};
vkGetBufferMemoryRequirements(device_, buffer, &requirements);
VkMemoryAllocateInfo allocate_info{};
allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocate_info.allocationSize = requirements.size;
allocate_info.memoryTypeIndex = find_memory_type(requirements.memoryTypeBits, property);
VK_CHECK(vkAllocateMemory(device_, &allocate_info, nullptr, device_memory));
}
void RenderEngine::create_instance() void RenderEngine::create_instance()
{ {
std::vector<const char*> extensions = get_required_extensions(); std::vector<const char*> extensions = get_required_extensions();
@@ -274,7 +340,9 @@ void RenderEngine::create_logical_device()
VkPhysicalDeviceFeatures device_features{}; VkPhysicalDeviceFeatures device_features{};
std::vector<VkDeviceQueueCreateInfo> queue_create_infos; std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
std::set<uint32_t> unique_queue_families = {indices.graphics_family.value(), indices.present_family.value()}; std::set<uint32_t> unique_queue_families = {indices.graphics_family.value(),
indices.present_family.value(),
indices.transfer_family.value()};
float queue_priority = 1.0f; float queue_priority = 1.0f;
VkDeviceQueueCreateInfo device_queue_create_info{}; VkDeviceQueueCreateInfo device_queue_create_info{};
@@ -309,6 +377,7 @@ void RenderEngine::create_logical_device()
VK_CHECK(vkCreateDevice(physical_device_, &device_create_info, nullptr, &device_)); VK_CHECK(vkCreateDevice(physical_device_, &device_create_info, nullptr, &device_));
vkGetDeviceQueue(device_, indices.graphics_family.value(), 0, &graphics_queue_); vkGetDeviceQueue(device_, indices.graphics_family.value(), 0, &graphics_queue_);
vkGetDeviceQueue(device_, indices.present_family.value(), 0, &present_queue_); vkGetDeviceQueue(device_, indices.present_family.value(), 0, &present_queue_);
vkGetDeviceQueue(device_, indices.transfer_family.value(), 0, &transfer_queue_);
} }
void RenderEngine::create_swapchain(VkPresentModeKHR desired_present_mode) void RenderEngine::create_swapchain(VkPresentModeKHR desired_present_mode)
@@ -338,12 +407,20 @@ void RenderEngine::create_swapchain(VkPresentModeKHR desired_present_mode)
swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; swapchain_create_info.oldSwapchain = VK_NULL_HANDLE;
QueueFamilyIndices family_indices = find_queue_family_indices(physical_device_, surface_); QueueFamilyIndices family_indices = find_queue_family_indices(physical_device_, surface_);
uint32_t queue_family_indices[] = {family_indices.graphics_family.value(), family_indices.present_family.value()}; const std::set<uint32_t> queue_family_indices = { family_indices.graphics_family.value(),
if (family_indices.graphics_family != family_indices.present_family) family_indices.present_family.value(),
family_indices.transfer_family.value() };
std::vector<uint32_t> arr_families;
if (queue_family_indices.size() > 1)
{ {
arr_families.reserve(queue_family_indices.size());
for(auto& i : queue_family_indices)
arr_families.push_back(i);
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
swapchain_create_info.queueFamilyIndexCount = 2; swapchain_create_info.queueFamilyIndexCount = static_cast<uint32_t>(arr_families.size());
swapchain_create_info.pQueueFamilyIndices = queue_family_indices; swapchain_create_info.pQueueFamilyIndices = arr_families.data();
} }
else else
{ {
@@ -614,29 +691,84 @@ uint32_t RenderEngine::find_memory_type(uint32_t typeFilter, VkMemoryPropertyFla
void RenderEngine::allocate_vertex_buffer() void RenderEngine::allocate_vertex_buffer()
{ {
VkBufferCreateInfo buffer_info{}; QueueFamilyIndices indices = find_queue_family_indices(physical_device_, surface_);
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; std::set<uint32_t> set_indices = {indices.graphics_family.value(),
buffer_info.size = sizeof(vertices[0]) * vertices.size(); indices.present_family.value(),
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; indices.transfer_family.value()};
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; std::vector<uint32_t> arr_indices;
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
arr_indices.reserve(set_indices.size());
for (auto& i : set_indices)
arr_indices.push_back(i);
VK_CHECK(vkCreateBuffer(device_, &buffer_info, nullptr, &vertex_buffer_));
VkMemoryRequirements requirements{}; VkBuffer staging_buffer = VK_NULL_HANDLE;
vkGetBufferMemoryRequirements(device_, vertex_buffer_, &requirements); VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
VkMemoryAllocateInfo allocate_info{}; VkDeviceSize size_buffer = sizeof(vertices[0]) * vertices.size();
allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index);
allocate_info.allocationSize = requirements.size; allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory);
allocate_info.memoryTypeIndex = find_memory_type(requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
VK_CHECK(vkAllocateMemory(device_, &allocate_info, nullptr, &vertex_buffer_memory_)); create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &vertex_buffer_, arr_indices);
allocate_memory(vertex_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertex_buffer_memory_);
VK_CHECK(vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0));
VK_CHECK(vkBindBufferMemory(device_, vertex_buffer_, vertex_buffer_memory_, 0)); VK_CHECK(vkBindBufferMemory(device_, vertex_buffer_, vertex_buffer_memory_, 0));
void* data; void* data;
VK_CHECK(vkMapMemory(device_, vertex_buffer_memory_, 0, buffer_info.size, 0, &data)); VK_CHECK(vkMapMemory(device_, staging_buffer_memory, 0, size_buffer, 0, &data));
memcpy(data, vertices.data(), buffer_info.size); memcpy(data, vertices.data(), size_buffer);
vkUnmapMemory(device_, vertex_buffer_memory_); vkUnmapMemory(device_, staging_buffer_memory);
copy_memory(staging_buffer, vertex_buffer_, size_buffer);
vkFreeMemory(device_, staging_buffer_memory, nullptr);
vkDestroyBuffer(device_, staging_buffer, nullptr);
}
void RenderEngine::copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size)
{
QueueFamilyIndices indices = find_queue_family_indices(physical_device_, surface_);
VkCommandPool copy_pool;
VkCommandPoolCreateInfo copy_pool_info{};
copy_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
copy_pool_info.queueFamilyIndex = indices.transfer_family.value();
copy_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VK_CHECK(vkCreateCommandPool(device_, &copy_pool_info, nullptr, &copy_pool));
VkCommandBufferAllocateInfo command_buffer_allocate_info{};
command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_buffer_allocate_info.commandPool = copy_pool;
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
command_buffer_allocate_info.commandBufferCount = 1;
VkCommandBuffer copy_buffer;
VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, &copy_buffer));
VkCommandBufferBeginInfo command_buffer_begin_info{};
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VK_CHECK(vkBeginCommandBuffer(copy_buffer, &command_buffer_begin_info));
VkBufferCopy buffer_copy{};
buffer_copy.srcOffset = 0;
buffer_copy.dstOffset = 0;
buffer_copy.size = size;
vkCmdCopyBuffer(copy_buffer, src, dst, 1, &buffer_copy);
vkEndCommandBuffer(copy_buffer);
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &copy_buffer;
vkQueueSubmit(transfer_queue_, 1, &submit_info, VK_NULL_HANDLE);
vkQueueWaitIdle(transfer_queue_);
vkFreeCommandBuffers(device_, copy_pool, 1, &copy_buffer);
vkDestroyCommandPool(device_, copy_pool, nullptr);
} }
void RenderEngine::allocate_command_buffers() void RenderEngine::allocate_command_buffers()
+6 -1
View File
@@ -26,7 +26,7 @@ class RenderEngine
{ {
std::optional<uint32_t> graphics_family; std::optional<uint32_t> graphics_family;
std::optional<uint32_t> present_family; std::optional<uint32_t> present_family;
bool is_complete() const; std::optional<uint32_t> transfer_family;
}; };
struct SwapchainSupportDetails struct SwapchainSupportDetails
{ {
@@ -52,6 +52,7 @@ class RenderEngine
VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE; VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE;
uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const; uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
void allocate_vertex_buffer(); void allocate_vertex_buffer();
void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size);
#pragma endregion #pragma endregion
static const std::vector<const char*> deviceExtensions; static const std::vector<const char*> deviceExtensions;
@@ -66,6 +67,7 @@ class RenderEngine
VkDevice device_ = VK_NULL_HANDLE; VkDevice device_ = VK_NULL_HANDLE;
VkQueue graphics_queue_ = VK_NULL_HANDLE; VkQueue graphics_queue_ = VK_NULL_HANDLE;
VkQueue present_queue_ = VK_NULL_HANDLE; VkQueue present_queue_ = VK_NULL_HANDLE;
VkQueue transfer_queue_ = VK_NULL_HANDLE;
VkSwapchainKHR swapchain_ = VK_NULL_HANDLE; VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
std::vector<VkImage> swapchain_images_; std::vector<VkImage> swapchain_images_;
VkFormat swapchain_image_format_; VkFormat swapchain_image_format_;
@@ -95,6 +97,9 @@ class RenderEngine
static VkPresentModeKHR choose_present_mode(const std::vector<VkPresentModeKHR>& present_modes, VkPresentModeKHR desired_present_mode); static VkPresentModeKHR choose_present_mode(const std::vector<VkPresentModeKHR>& present_modes, VkPresentModeKHR desired_present_mode);
static VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window); static VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
VkShaderModule create_shader_module(const std::string& code) const; VkShaderModule create_shader_module(const std::string& code) const;
void create_buffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkBuffer* buffer, const std::vector<uint32_t>& queue_families);
void allocate_memory(VkBuffer buffer, VkMemoryPropertyFlags property, VkDeviceMemory* device_memory);
void create_instance(); void create_instance();
void create_surface(); void create_surface();