Add "copy_memory"
This commit is contained in:
+166
-34
@@ -66,12 +66,6 @@ std::vector<const char*> RenderEngine::get_required_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 description;
|
||||
@@ -103,9 +97,13 @@ bool RenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surf
|
||||
vkGetPhysicalDeviceProperties(device, &device_properties);
|
||||
vkGetPhysicalDeviceFeatures(device, &device_features);
|
||||
|
||||
try {
|
||||
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)
|
||||
@@ -141,19 +139,50 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi
|
||||
std::vector<VkQueueFamilyProperties> family_properties(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, family_properties.data());
|
||||
|
||||
// Find graphics
|
||||
for(uint32_t i = 0; i < family_properties.size(); ++i)
|
||||
{
|
||||
if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -206,6 +235,43 @@ VkShaderModule RenderEngine::create_shader_module(const std::string& code) const
|
||||
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()
|
||||
{
|
||||
std::vector<const char*> extensions = get_required_extensions();
|
||||
@@ -274,7 +340,9 @@ void RenderEngine::create_logical_device()
|
||||
VkPhysicalDeviceFeatures device_features{};
|
||||
|
||||
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;
|
||||
VkDeviceQueueCreateInfo device_queue_create_info{};
|
||||
@@ -309,6 +377,7 @@ void RenderEngine::create_logical_device()
|
||||
VK_CHECK(vkCreateDevice(physical_device_, &device_create_info, nullptr, &device_));
|
||||
vkGetDeviceQueue(device_, indices.graphics_family.value(), 0, &graphics_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)
|
||||
@@ -338,12 +407,20 @@ void RenderEngine::create_swapchain(VkPresentModeKHR desired_present_mode)
|
||||
swapchain_create_info.oldSwapchain = VK_NULL_HANDLE;
|
||||
|
||||
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()};
|
||||
if (family_indices.graphics_family != family_indices.present_family)
|
||||
const std::set<uint32_t> queue_family_indices = { family_indices.graphics_family.value(),
|
||||
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.queueFamilyIndexCount = 2;
|
||||
swapchain_create_info.pQueueFamilyIndices = queue_family_indices;
|
||||
swapchain_create_info.queueFamilyIndexCount = static_cast<uint32_t>(arr_families.size());
|
||||
swapchain_create_info.pQueueFamilyIndices = arr_families.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -614,29 +691,84 @@ uint32_t RenderEngine::find_memory_type(uint32_t typeFilter, VkMemoryPropertyFla
|
||||
|
||||
void RenderEngine::allocate_vertex_buffer()
|
||||
{
|
||||
VkBufferCreateInfo buffer_info{};
|
||||
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_info.size = sizeof(vertices[0]) * vertices.size();
|
||||
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
QueueFamilyIndices indices = find_queue_family_indices(physical_device_, surface_);
|
||||
std::set<uint32_t> set_indices = {indices.graphics_family.value(),
|
||||
indices.present_family.value(),
|
||||
indices.transfer_family.value()};
|
||||
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{};
|
||||
vkGetBufferMemoryRequirements(device_, vertex_buffer_, &requirements);
|
||||
VkBuffer staging_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
|
||||
|
||||
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, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
VkDeviceSize size_buffer = sizeof(vertices[0]) * vertices.size();
|
||||
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index);
|
||||
allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory);
|
||||
|
||||
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));
|
||||
|
||||
void* data;
|
||||
VK_CHECK(vkMapMemory(device_, vertex_buffer_memory_, 0, buffer_info.size, 0, &data));
|
||||
memcpy(data, vertices.data(), buffer_info.size);
|
||||
vkUnmapMemory(device_, vertex_buffer_memory_);
|
||||
VK_CHECK(vkMapMemory(device_, staging_buffer_memory, 0, size_buffer, 0, &data));
|
||||
memcpy(data, vertices.data(), size_buffer);
|
||||
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()
|
||||
|
||||
@@ -26,7 +26,7 @@ class RenderEngine
|
||||
{
|
||||
std::optional<uint32_t> graphics_family;
|
||||
std::optional<uint32_t> present_family;
|
||||
bool is_complete() const;
|
||||
std::optional<uint32_t> transfer_family;
|
||||
};
|
||||
struct SwapchainSupportDetails
|
||||
{
|
||||
@@ -52,6 +52,7 @@ class RenderEngine
|
||||
VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE;
|
||||
uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
|
||||
void allocate_vertex_buffer();
|
||||
void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
||||
#pragma endregion
|
||||
|
||||
static const std::vector<const char*> deviceExtensions;
|
||||
@@ -66,6 +67,7 @@ class RenderEngine
|
||||
VkDevice device_ = VK_NULL_HANDLE;
|
||||
VkQueue graphics_queue_ = VK_NULL_HANDLE;
|
||||
VkQueue present_queue_ = VK_NULL_HANDLE;
|
||||
VkQueue transfer_queue_ = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
|
||||
std::vector<VkImage> swapchain_images_;
|
||||
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 VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
|
||||
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_surface();
|
||||
|
||||
Reference in New Issue
Block a user