Add "copy_memory"
This commit is contained in:
+166
-34
@@ -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_, ©_pool_info, nullptr, ©_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, ©_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 = ©_buffer;
|
||||||
|
|
||||||
|
vkQueueSubmit(transfer_queue_, 1, &submit_info, VK_NULL_HANDLE);
|
||||||
|
vkQueueWaitIdle(transfer_queue_);
|
||||||
|
|
||||||
|
vkFreeCommandBuffers(device_, copy_pool, 1, ©_buffer);
|
||||||
|
vkDestroyCommandPool(device_, copy_pool, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderEngine::allocate_command_buffers()
|
void RenderEngine::allocate_command_buffers()
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user