Add RenderEngineSDK
This commit is contained in:
@@ -0,0 +1,125 @@
|
|||||||
|
#include "DeviceFunctions.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
VkExtent2D DeviceFunctions::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
|
||||||
|
{
|
||||||
|
// The acceptable rendering sparsity is calculated here
|
||||||
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
||||||
|
return capabilities.currentExtent;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
|
VkExtent2D actualExtent = {
|
||||||
|
static_cast<uint32_t>(width),
|
||||||
|
static_cast<uint32_t>(height)
|
||||||
|
};
|
||||||
|
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
|
||||||
|
return actualExtent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DeviceFunctions::find_memory_type(VkPhysicalDevice physical_device, uint32_t typeFilter,
|
||||||
|
VkMemoryPropertyFlags properties)
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceMemoryProperties memory_properties{};
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i)
|
||||||
|
{
|
||||||
|
if (typeFilter & (1 << i) && (memory_properties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("failed to find suitable memory type!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceFunctions::device_memcpy(VkDevice device, uint32_t transfer_queue_family, VkBuffer src, VkBuffer dst, size_t size)
|
||||||
|
{
|
||||||
|
VkCommandPool copy_pool;
|
||||||
|
VkCommandPoolCreateInfo copy_pool_info{};
|
||||||
|
copy_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
copy_pool_info.queueFamilyIndex = transfer_queue_family;
|
||||||
|
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;
|
||||||
|
|
||||||
|
VkQueue transfer_queue;
|
||||||
|
vkGetDeviceQueue(device, transfer_queue_family, 0, &transfer_queue);
|
||||||
|
|
||||||
|
vkQueueSubmit(transfer_queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||||
|
vkQueueWaitIdle(transfer_queue);
|
||||||
|
|
||||||
|
vkFreeCommandBuffers(device, copy_pool, 1, ©_buffer);
|
||||||
|
vkDestroyCommandPool(device, copy_pool, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkBuffer DeviceFunctions::create_buffer(VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkBuffer buffer;
|
||||||
|
VK_CHECK(vkCreateBuffer(device, &buffer_info, nullptr, &buffer));
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceMemory DeviceFunctions::allocate_device_memory(VkPhysicalDevice physical_device, VkDevice device, VkBuffer buffer, VkMemoryPropertyFlags property)
|
||||||
|
{
|
||||||
|
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(physical_device, requirements.memoryTypeBits, property);
|
||||||
|
|
||||||
|
VkDeviceMemory device_memory;
|
||||||
|
VK_CHECK(vkAllocateMemory(device, &allocate_info, nullptr, &device_memory));
|
||||||
|
return device_memory;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define GLFW_INCLUDE_VULKAN
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#include <assert.h>
|
||||||
|
#define VK_CHECK(res) assert(res == VK_SUCCESS);
|
||||||
|
#else
|
||||||
|
#define VK_CHECK(val) {int res = (val); if ((res) != VK_SUCCESS) throw std::runtime_error("Vulkan error: " + std::to_string(static_cast<int>(res)));}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace DeviceFunctions
|
||||||
|
{
|
||||||
|
VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
|
||||||
|
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||||
|
void device_memcpy(VkDevice device, uint32_t transfer_queue_family, VkBuffer src, VkBuffer dst, size_t size);
|
||||||
|
VkBuffer create_buffer(VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, const std::vector<uint32_t>& queue_families);
|
||||||
|
VkDeviceMemory allocate_device_memory(VkPhysicalDevice physical_device, VkDevice device, VkBuffer buffer, VkMemoryPropertyFlags property);
|
||||||
|
}
|
||||||
@@ -2,6 +2,6 @@ file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.hpp" "*.h")
|
|||||||
|
|
||||||
add_library(UwURenderEngine ${SRC})
|
add_library(UwURenderEngine ${SRC})
|
||||||
target_include_directories(UwURenderEngine PUBLIC ${PROJECT_SOURCE_DIR}/RenderEngineSDK)
|
target_include_directories(UwURenderEngine PUBLIC ${PROJECT_SOURCE_DIR}/RenderEngineSDK)
|
||||||
target_link_libraries(UwURenderEngine PRIVATE RenderEngineSDK)
|
target_link_libraries(UwURenderEngine PUBLIC RenderEngineSDK)
|
||||||
|
|
||||||
target_compile_features(UwURenderEngine PRIVATE cxx_std_17)
|
target_compile_features(UwURenderEngine PRIVATE cxx_std_17)
|
||||||
@@ -1,7 +1,47 @@
|
|||||||
#include "ModelManager.hpp"
|
#include "ModelManager.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "Log/Log.hpp"
|
#include "Log/Log.hpp"
|
||||||
|
|
||||||
|
ModelManager::StaticModel::StaticModel(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices,
|
||||||
|
VkPhysicalDevice physical_device, VkDevice device):
|
||||||
|
physical_device_(physical_device),
|
||||||
|
device_(device)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelManager::StaticModel::~StaticModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VkVertexInputBindingDescription ModelManager::Vertex::get_binding_description()
|
||||||
|
{
|
||||||
|
VkVertexInputBindingDescription description;
|
||||||
|
description.binding = 0;
|
||||||
|
description.stride = sizeof(Vertex);
|
||||||
|
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<VkVertexInputAttributeDescription, 2> ModelManager::Vertex::get_vertex_attribute_descriptions()
|
||||||
|
{
|
||||||
|
std::array<VkVertexInputAttributeDescription, 2> descriptions;
|
||||||
|
// Bind vertex loc
|
||||||
|
descriptions[0].binding = 0;
|
||||||
|
descriptions[0].location = 0;
|
||||||
|
descriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
descriptions[0].offset = offsetof(Vertex, pos);
|
||||||
|
|
||||||
|
// Bind color
|
||||||
|
descriptions[1].binding = 0;
|
||||||
|
descriptions[1].location = 1;
|
||||||
|
descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
descriptions[1].offset = offsetof(Vertex, color);
|
||||||
|
|
||||||
|
return descriptions;
|
||||||
|
}
|
||||||
|
|
||||||
ModelManager::owner_counter::owner_counter(const owner_counter& other) : counter(other.counter.load()), model(other.model)
|
ModelManager::owner_counter::owner_counter(const owner_counter& other) : counter(other.counter.load()), model(other.model)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -19,6 +59,11 @@ unsigned int ModelManager::FNV1aHash(const char* buf)
|
|||||||
return h_val;
|
return h_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelManager::ModelManager(VkPhysicalDevice physical_device, VkDevice device):
|
||||||
|
physical_device_(physical_device),
|
||||||
|
device_(device)
|
||||||
|
{}
|
||||||
|
|
||||||
ModelManager::~ModelManager()
|
ModelManager::~ModelManager()
|
||||||
{
|
{
|
||||||
models.clear();
|
models.clear();
|
||||||
@@ -38,10 +83,13 @@ ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name)
|
|||||||
|
|
||||||
Loging::Log("Load new model: " + name);
|
Loging::Log("Load new model: " + name);
|
||||||
|
|
||||||
|
std::vector<Vertex> vertices;
|
||||||
|
std::vector<uint32_t> indices;
|
||||||
// Load model_data
|
// Load model_data
|
||||||
|
|
||||||
owner_counter new_counter;
|
owner_counter new_counter;
|
||||||
new_counter.counter.store(1);
|
new_counter.counter.store(1);
|
||||||
new_counter.model = new StaticModel();
|
new_counter.model = new StaticModel(vertices, indices, physical_device_, device_);
|
||||||
models.try_emplace(hash, new_counter);
|
models.try_emplace(hash, new_counter);
|
||||||
return new_counter.model;
|
return new_counter.model;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,33 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
class ModelManager
|
class ModelManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
glm::vec3 pos, color;
|
||||||
|
static VkVertexInputBindingDescription get_binding_description();
|
||||||
|
static std::array<VkVertexInputAttributeDescription, 2> get_vertex_attribute_descriptions();
|
||||||
|
|
||||||
|
};
|
||||||
class StaticModel
|
class StaticModel
|
||||||
{
|
{
|
||||||
//DATA
|
VkPhysicalDevice physical_device_;
|
||||||
|
VkDevice device_;
|
||||||
|
VkBuffer vertex_buffer_;
|
||||||
|
VkBuffer index_buffer_;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
StaticModel(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices,
|
||||||
|
VkPhysicalDevice physical_device, VkDevice device);
|
||||||
|
~StaticModel();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct owner_counter
|
struct owner_counter
|
||||||
@@ -22,12 +42,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
VkPhysicalDevice physical_device_;
|
||||||
|
VkDevice device_;
|
||||||
std::unordered_map<unsigned int, owner_counter> models;
|
std::unordered_map<unsigned int, owner_counter> models;
|
||||||
|
|
||||||
static unsigned int FNV1aHash (const char *buf);
|
static unsigned int FNV1aHash (const char *buf);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ModelManager(VkPhysicalDevice physical_device, VkDevice device);
|
||||||
~ModelManager();
|
~ModelManager();
|
||||||
|
|
||||||
StaticModel* LoadModel(const std::string& name);
|
StaticModel* LoadModel(const std::string& name);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Game/GameInstance.hpp"
|
#include "Game/GameInstance.hpp"
|
||||||
#include "Game/World/World.hpp"
|
#include "Game/World/World.hpp"
|
||||||
#include "../Game/Actors/Mesh/Mesh.hpp"
|
#include "../Game/Actors/Mesh/Mesh.hpp"
|
||||||
|
#include "DeviceFunctions/DeviceFunctions.hpp"
|
||||||
|
|
||||||
const std::vector<const char*> UwURenderEngine::deviceExtensions = {
|
const std::vector<const char*> UwURenderEngine::deviceExtensions = {
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||||
@@ -47,14 +48,14 @@ UwURenderEngine::SwapchainSupportDetails UwURenderEngine::query_swapchain_detail
|
|||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device_, surface_, &details.capabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device_, surface_, &details.capabilities);
|
||||||
|
|
||||||
uint32_t surface_format_cnt = 0;
|
uint32_t surface_format_cnt = 0;
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, nullptr));
|
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, nullptr))
|
||||||
details.formats.resize(surface_format_cnt);
|
details.formats.resize(surface_format_cnt);
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, details.formats.data()));
|
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, details.formats.data()))
|
||||||
|
|
||||||
uint32_t present_modes_cnt = 0;
|
uint32_t present_modes_cnt = 0;
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, nullptr));
|
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, nullptr))
|
||||||
details.present_modes.resize(surface_format_cnt);
|
details.present_modes.resize(surface_format_cnt);
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, details.present_modes.data()));
|
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, details.present_modes.data()))
|
||||||
|
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
@@ -71,33 +72,6 @@ std::vector<const char*> UwURenderEngine::get_required_extensions()
|
|||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkVertexInputBindingDescription UwURenderEngine::Vertex::get_binding_description()
|
|
||||||
{
|
|
||||||
VkVertexInputBindingDescription description;
|
|
||||||
description.binding = 0;
|
|
||||||
description.stride = sizeof(Vertex);
|
|
||||||
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<VkVertexInputAttributeDescription, 2> UwURenderEngine::Vertex::get_vertex_attribute_descriptions()
|
|
||||||
{
|
|
||||||
std::array<VkVertexInputAttributeDescription, 2> descriptions;
|
|
||||||
// Bind vertex loc
|
|
||||||
descriptions[0].binding = 0;
|
|
||||||
descriptions[0].location = 0;
|
|
||||||
descriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
||||||
descriptions[0].offset = offsetof(Vertex, pos);
|
|
||||||
|
|
||||||
// Bind color
|
|
||||||
descriptions[1].binding = 0;
|
|
||||||
descriptions[1].location = 1;
|
|
||||||
descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
||||||
descriptions[1].offset = offsetof(Vertex, color);
|
|
||||||
|
|
||||||
return descriptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface)
|
bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface)
|
||||||
{
|
{
|
||||||
VkPhysicalDeviceProperties device_properties;
|
VkPhysicalDeviceProperties device_properties;
|
||||||
@@ -107,7 +81,7 @@ bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR s
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Ловить исключения имеет смысыл только здесь
|
// Ловить исключения имеет смысыл только здесь
|
||||||
QueueFamilyIndices indices = find_queue_family_indices(device, surface);
|
find_queue_family_indices(device, surface);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -118,9 +92,9 @@ bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR s
|
|||||||
bool UwURenderEngine::check_device_extensions_support(VkPhysicalDevice device)
|
bool UwURenderEngine::check_device_extensions_support(VkPhysicalDevice device)
|
||||||
{
|
{
|
||||||
uint32_t extension_count;
|
uint32_t extension_count;
|
||||||
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr));
|
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr))
|
||||||
std::vector<VkExtensionProperties> available_extensions(extension_count);
|
std::vector<VkExtensionProperties> available_extensions(extension_count);
|
||||||
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data()));
|
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data()))
|
||||||
|
|
||||||
for (const auto& extension : deviceExtensions)
|
for (const auto& extension : deviceExtensions)
|
||||||
{
|
{
|
||||||
@@ -163,7 +137,7 @@ UwURenderEngine::QueueFamilyIndices UwURenderEngine::find_queue_family_indices(V
|
|||||||
|
|
||||||
// Find present
|
// Find present
|
||||||
VkBool32 present_support = false;
|
VkBool32 present_support = false;
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family.value(), surface, &present_support));
|
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family.value(), surface, &present_support))
|
||||||
// Если графическая очередь поддерживет презентацию кадров, то используем её
|
// Если графическая очередь поддерживет презентацию кадров, то используем её
|
||||||
if (present_support == VK_TRUE)
|
if (present_support == VK_TRUE)
|
||||||
queue_family_indices.present_family = queue_family_indices.graphics_family;
|
queue_family_indices.present_family = queue_family_indices.graphics_family;
|
||||||
@@ -173,7 +147,7 @@ UwURenderEngine::QueueFamilyIndices UwURenderEngine::find_queue_family_indices(V
|
|||||||
for(uint32_t i = 0; i < family_properties.size(); ++i)
|
for(uint32_t i = 0; i < family_properties.size(); ++i)
|
||||||
{
|
{
|
||||||
present_support = false;
|
present_support = false;
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support));
|
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support))
|
||||||
if (present_support == VK_TRUE)
|
if (present_support == VK_TRUE)
|
||||||
{
|
{
|
||||||
queue_family_indices.present_family = i;
|
queue_family_indices.present_family = i;
|
||||||
@@ -220,24 +194,6 @@ VkPresentModeKHR UwURenderEngine::choose_present_mode(const std::vector<VkPresen
|
|||||||
return VK_PRESENT_MODE_FIFO_KHR;
|
return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkExtent2D UwURenderEngine::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
|
|
||||||
{
|
|
||||||
// Здесь вычисляется допустимое разрешение рендера
|
|
||||||
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
|
||||||
return capabilities.currentExtent;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int width, height;
|
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
|
||||||
VkExtent2D actualExtent = {
|
|
||||||
static_cast<uint32_t>(width),
|
|
||||||
static_cast<uint32_t>(height)
|
|
||||||
};
|
|
||||||
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
|
|
||||||
return actualExtent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VkShaderModule UwURenderEngine::create_shader_module(const std::string& code) const
|
VkShaderModule UwURenderEngine::create_shader_module(const std::string& code) const
|
||||||
{
|
{
|
||||||
VkShaderModuleCreateInfo shader_module_info{};
|
VkShaderModuleCreateInfo shader_module_info{};
|
||||||
@@ -246,47 +202,10 @@ VkShaderModule UwURenderEngine::create_shader_module(const std::string& code) co
|
|||||||
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(code.c_str());
|
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(code.c_str());
|
||||||
|
|
||||||
VkShaderModule shader_module;
|
VkShaderModule shader_module;
|
||||||
VK_CHECK(vkCreateShaderModule(device_, &shader_module_info, nullptr, &shader_module));
|
VK_CHECK(vkCreateShaderModule(device_, &shader_module_info, nullptr, &shader_module))
|
||||||
return shader_module;
|
return shader_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::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 UwURenderEngine::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 UwURenderEngine::create_instance()
|
void UwURenderEngine::create_instance()
|
||||||
{
|
{
|
||||||
std::vector<const char*> extensions = get_required_extensions();
|
std::vector<const char*> extensions = get_required_extensions();
|
||||||
@@ -318,9 +237,9 @@ void UwURenderEngine::create_instance()
|
|||||||
debug_messenger_create_info.pfnUserCallback = &debugCallback;
|
debug_messenger_create_info.pfnUserCallback = &debugCallback;
|
||||||
instance_create_info.pNext = &debug_messenger_create_info;
|
instance_create_info.pNext = &debug_messenger_create_info;
|
||||||
#endif
|
#endif
|
||||||
VK_CHECK(vkCreateInstance(&instance_create_info, nullptr, &instance_));
|
VK_CHECK(vkCreateInstance(&instance_create_info, nullptr, &instance_))
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
VK_CHECK(enable_layer_validation(&debug_messenger_create_info));
|
VK_CHECK(enable_layer_validation(&debug_messenger_create_info))
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,9 +247,9 @@ void UwURenderEngine::pick_physical_device()
|
|||||||
{
|
{
|
||||||
uint32_t device_count = 0;
|
uint32_t device_count = 0;
|
||||||
std::vector<VkPhysicalDevice> devices;
|
std::vector<VkPhysicalDevice> devices;
|
||||||
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, nullptr));
|
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, nullptr))
|
||||||
devices.resize(device_count);
|
devices.resize(device_count);
|
||||||
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, devices.data()));
|
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, devices.data()))
|
||||||
|
|
||||||
for (const auto& device : devices)
|
for (const auto& device : devices)
|
||||||
{
|
{
|
||||||
@@ -389,7 +308,7 @@ void UwURenderEngine::create_logical_device()
|
|||||||
device_create_info.ppEnabledLayerNames = nullptr;
|
device_create_info.ppEnabledLayerNames = nullptr;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
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_);
|
vkGetDeviceQueue(device_, indices.transfer_family.value(), 0, &transfer_queue_);
|
||||||
@@ -400,7 +319,7 @@ void UwURenderEngine::create_swapchain()
|
|||||||
SwapchainSupportDetails swapchain_support = query_swapchain_details();
|
SwapchainSupportDetails swapchain_support = query_swapchain_details();
|
||||||
VkSurfaceFormatKHR surface_format = choose_surface_format(swapchain_support.formats);
|
VkSurfaceFormatKHR surface_format = choose_surface_format(swapchain_support.formats);
|
||||||
VkPresentModeKHR present_mode = choose_present_mode(swapchain_support.present_modes, VK_PRESENT_MODE_MAILBOX_KHR);
|
VkPresentModeKHR present_mode = choose_present_mode(swapchain_support.present_modes, VK_PRESENT_MODE_MAILBOX_KHR);
|
||||||
VkExtent2D extent = choose_extent(swapchain_support.capabilities, get_window());
|
VkExtent2D extent = DeviceFunctions::choose_extent(swapchain_support.capabilities, get_window());
|
||||||
|
|
||||||
uint32_t image_count = swapchain_support.capabilities.minImageCount + 1;
|
uint32_t image_count = swapchain_support.capabilities.minImageCount + 1;
|
||||||
if (swapchain_support.capabilities.maxImageCount > 0 && image_count > swapchain_support.capabilities.maxImageCount)
|
if (swapchain_support.capabilities.maxImageCount > 0 && image_count > swapchain_support.capabilities.maxImageCount)
|
||||||
@@ -444,7 +363,7 @@ void UwURenderEngine::create_swapchain()
|
|||||||
swapchain_create_info.pQueueFamilyIndices = nullptr;
|
swapchain_create_info.pQueueFamilyIndices = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VK_CHECK(vkCreateSwapchainKHR(device_, &swapchain_create_info, nullptr, &swapchain_));
|
VK_CHECK(vkCreateSwapchainKHR(device_, &swapchain_create_info, nullptr, &swapchain_))
|
||||||
|
|
||||||
vkGetSwapchainImagesKHR(device_, swapchain_, &image_count, nullptr);
|
vkGetSwapchainImagesKHR(device_, swapchain_, &image_count, nullptr);
|
||||||
swapchain_images_.resize(image_count);
|
swapchain_images_.resize(image_count);
|
||||||
@@ -474,7 +393,7 @@ void UwURenderEngine::create_image_views()
|
|||||||
for (uint32_t i = 0; i < swapchain_images_.size(); ++i)
|
for (uint32_t i = 0; i < swapchain_images_.size(); ++i)
|
||||||
{
|
{
|
||||||
image_view_info.image = swapchain_images_[i];
|
image_view_info.image = swapchain_images_[i];
|
||||||
VK_CHECK(vkCreateImageView(device_, &image_view_info, nullptr, &swapchain_image_views_[i]));
|
VK_CHECK(vkCreateImageView(device_, &image_view_info, nullptr, &swapchain_image_views_[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +435,7 @@ void UwURenderEngine::create_render_pass()
|
|||||||
render_pass_info.dependencyCount = 1;
|
render_pass_info.dependencyCount = 1;
|
||||||
render_pass_info.pDependencies = &dependency;
|
render_pass_info.pDependencies = &dependency;
|
||||||
|
|
||||||
VK_CHECK(vkCreateRenderPass(device_, &render_pass_info, nullptr, &render_pass_));
|
VK_CHECK(vkCreateRenderPass(device_, &render_pass_info, nullptr, &render_pass_))
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::create_description_set_layout()
|
void UwURenderEngine::create_description_set_layout()
|
||||||
@@ -533,7 +452,7 @@ void UwURenderEngine::create_description_set_layout()
|
|||||||
ubo_layout_info.bindingCount = 1;
|
ubo_layout_info.bindingCount = 1;
|
||||||
ubo_layout_info.pBindings = &ubo_layout_binding;
|
ubo_layout_info.pBindings = &ubo_layout_binding;
|
||||||
|
|
||||||
VK_CHECK(vkCreateDescriptorSetLayout(device_, &ubo_layout_info, nullptr, &ubo_layout_binding_));
|
VK_CHECK(vkCreateDescriptorSetLayout(device_, &ubo_layout_info, nullptr, &ubo_layout_binding_))
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::create_uniform_buffers()
|
void UwURenderEngine::create_uniform_buffers()
|
||||||
@@ -546,8 +465,8 @@ void UwURenderEngine::create_uniform_buffers()
|
|||||||
for (size_t i = 0; i < swapchain_images_.size(); ++i)
|
for (size_t i = 0; i < swapchain_images_.size(); ++i)
|
||||||
{
|
{
|
||||||
const VkDeviceSize size = sizeof(UniformBufferObject);
|
const VkDeviceSize size = sizeof(UniformBufferObject);
|
||||||
create_buffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &uniform_buffers_[i], arr_indices);
|
uniform_buffers_[i] = DeviceFunctions::create_buffer(device_, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, arr_indices);
|
||||||
allocate_memory(uniform_buffers_[i], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniform_buffers_memory_[i]);
|
uniform_buffers_memory_[i] = DeviceFunctions::allocate_device_memory(physical_device_, device_, uniform_buffers_[i], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
vkBindBufferMemory(device_, uniform_buffers_[i], uniform_buffers_memory_[i], 0);
|
vkBindBufferMemory(device_, uniform_buffers_[i], uniform_buffers_memory_[i], 0);
|
||||||
|
|
||||||
vkMapMemory(device_, uniform_buffers_memory_[i], 0, size, 0, &uniform_buffers_mapped_[i]);
|
vkMapMemory(device_, uniform_buffers_memory_[i], 0, size, 0, &uniform_buffers_mapped_[i]);
|
||||||
@@ -566,7 +485,7 @@ void UwURenderEngine::create_descriptor_pool()
|
|||||||
descriptor_pool_info.pPoolSizes = &pool_size;
|
descriptor_pool_info.pPoolSizes = &pool_size;
|
||||||
descriptor_pool_info.maxSets = static_cast<uint32_t>(swapchain_images_.size());
|
descriptor_pool_info.maxSets = static_cast<uint32_t>(swapchain_images_.size());
|
||||||
|
|
||||||
VK_CHECK(vkCreateDescriptorPool(device_, &descriptor_pool_info, nullptr, &descriptor_pool_));
|
VK_CHECK(vkCreateDescriptorPool(device_, &descriptor_pool_info, nullptr, &descriptor_pool_))
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::create_descriptor_sets()
|
void UwURenderEngine::create_descriptor_sets()
|
||||||
@@ -579,7 +498,7 @@ void UwURenderEngine::create_descriptor_sets()
|
|||||||
descriptor_set_allocate_info.pSetLayouts = layouts.data();
|
descriptor_set_allocate_info.pSetLayouts = layouts.data();
|
||||||
|
|
||||||
descriptor_sets_.resize(swapchain_images_.size());
|
descriptor_sets_.resize(swapchain_images_.size());
|
||||||
VK_CHECK(vkAllocateDescriptorSets(device_, &descriptor_set_allocate_info, descriptor_sets_.data()));
|
VK_CHECK(vkAllocateDescriptorSets(device_, &descriptor_set_allocate_info, descriptor_sets_.data()))
|
||||||
|
|
||||||
for (size_t i = 0; i < swapchain_images_.size(); ++i)
|
for (size_t i = 0; i < swapchain_images_.size(); ++i)
|
||||||
{
|
{
|
||||||
@@ -645,8 +564,8 @@ void UwURenderEngine::create_graphics_pipeline()
|
|||||||
dynamic_state_info.dynamicStateCount = static_cast<uint32_t>(dynamic_states.size());
|
dynamic_state_info.dynamicStateCount = static_cast<uint32_t>(dynamic_states.size());
|
||||||
dynamic_state_info.pDynamicStates = dynamic_states.data();
|
dynamic_state_info.pDynamicStates = dynamic_states.data();
|
||||||
|
|
||||||
VkVertexInputBindingDescription binding_description = Vertex::get_binding_description();
|
VkVertexInputBindingDescription binding_description = ModelManager::Vertex::get_binding_description();
|
||||||
std::array<VkVertexInputAttributeDescription, 2> attribute_descriptions = Vertex::get_vertex_attribute_descriptions();
|
std::array<VkVertexInputAttributeDescription, 2> attribute_descriptions = ModelManager::Vertex::get_vertex_attribute_descriptions();
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertex_input_info{};
|
VkPipelineVertexInputStateCreateInfo vertex_input_info{};
|
||||||
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
@@ -719,7 +638,7 @@ void UwURenderEngine::create_graphics_pipeline()
|
|||||||
pipeline_layout_info.setLayoutCount = 1;
|
pipeline_layout_info.setLayoutCount = 1;
|
||||||
pipeline_layout_info.pSetLayouts = &ubo_layout_binding_;
|
pipeline_layout_info.pSetLayouts = &ubo_layout_binding_;
|
||||||
|
|
||||||
VK_CHECK(vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr, &pipeline_layout_));
|
VK_CHECK(vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr, &pipeline_layout_))
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo graphics_pipeline_info{};
|
VkGraphicsPipelineCreateInfo graphics_pipeline_info{};
|
||||||
graphics_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
graphics_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
@@ -739,7 +658,7 @@ void UwURenderEngine::create_graphics_pipeline()
|
|||||||
graphics_pipeline_info.basePipelineHandle = nullptr;
|
graphics_pipeline_info.basePipelineHandle = nullptr;
|
||||||
graphics_pipeline_info.basePipelineIndex = -1;
|
graphics_pipeline_info.basePipelineIndex = -1;
|
||||||
|
|
||||||
VK_CHECK(vkCreateGraphicsPipelines(device_, nullptr, 1, &graphics_pipeline_info, nullptr, &graphics_pipeline_));
|
VK_CHECK(vkCreateGraphicsPipelines(device_, nullptr, 1, &graphics_pipeline_info, nullptr, &graphics_pipeline_))
|
||||||
|
|
||||||
vkDestroyShaderModule(device_, vertex_shader, nullptr);
|
vkDestroyShaderModule(device_, vertex_shader, nullptr);
|
||||||
vkDestroyShaderModule(device_, fragment_shader, nullptr);
|
vkDestroyShaderModule(device_, fragment_shader, nullptr);
|
||||||
@@ -760,7 +679,7 @@ void UwURenderEngine::create_framebuffers()
|
|||||||
for (size_t i = 0; i < framebuffers_.size(); ++i)
|
for (size_t i = 0; i < framebuffers_.size(); ++i)
|
||||||
{
|
{
|
||||||
framebuffer_info.pAttachments = &swapchain_image_views_[i];
|
framebuffer_info.pAttachments = &swapchain_image_views_[i];
|
||||||
VK_CHECK(vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &framebuffers_[i]));
|
VK_CHECK(vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &framebuffers_[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,21 +692,7 @@ void UwURenderEngine::create_command_pool()
|
|||||||
command_pool_info.queueFamilyIndex = queue_family_indices.graphics_family.value();
|
command_pool_info.queueFamilyIndex = queue_family_indices.graphics_family.value();
|
||||||
command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
|
|
||||||
VK_CHECK(vkCreateCommandPool(device_, &command_pool_info, nullptr, &command_pool_));
|
VK_CHECK(vkCreateCommandPool(device_, &command_pool_info, nullptr, &command_pool_))
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t UwURenderEngine::find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const
|
|
||||||
{
|
|
||||||
VkPhysicalDeviceMemoryProperties memory_properties{};
|
|
||||||
vkGetPhysicalDeviceMemoryProperties(physical_device_, &memory_properties);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i)
|
|
||||||
{
|
|
||||||
if (typeFilter & (1 << i) && (memory_properties.memoryTypes[i].propertyFlags & properties) == properties)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("failed to find suitable memory type!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> UwURenderEngine::get_unique_family_indices(const QueueFamilyIndices& indices)
|
std::vector<uint32_t> UwURenderEngine::get_unique_family_indices(const QueueFamilyIndices& indices)
|
||||||
@@ -811,25 +716,25 @@ void UwURenderEngine::allocate_vertex_buffer()
|
|||||||
std::vector<uint32_t> arr_indices = get_unique_family_indices(indices);
|
std::vector<uint32_t> arr_indices = get_unique_family_indices(indices);
|
||||||
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
|
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
|
||||||
|
|
||||||
VkBuffer staging_buffer = VK_NULL_HANDLE;
|
|
||||||
VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
VkDeviceSize size_buffer = sizeof(vertices_[0]) * vertices_.size();
|
VkDeviceSize size_buffer = sizeof(vertices_[0]) * vertices_.size();
|
||||||
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index);
|
VkBuffer staging_buffer = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory);
|
transfer_index);
|
||||||
|
VkDeviceMemory staging_buffer_memory = DeviceFunctions::allocate_device_memory(
|
||||||
|
physical_device_, device_, staging_buffer,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &vertex_buffer_, arr_indices);
|
vertex_buffer_ = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, arr_indices);
|
||||||
allocate_memory(vertex_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertex_buffer_memory_);
|
vertex_buffer_memory_ = DeviceFunctions::allocate_device_memory(physical_device_, device_, vertex_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
VK_CHECK(vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0));
|
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_, staging_buffer_memory, 0, size_buffer, 0, &data));
|
VK_CHECK(vkMapMemory(device_, staging_buffer_memory, 0, size_buffer, 0, &data))
|
||||||
memcpy(data, vertices_.data(), size_buffer);
|
memcpy(data, vertices_.data(), size_buffer);
|
||||||
vkUnmapMemory(device_, staging_buffer_memory);
|
vkUnmapMemory(device_, staging_buffer_memory);
|
||||||
|
|
||||||
copy_memory(staging_buffer, vertex_buffer_, size_buffer);
|
DeviceFunctions::device_memcpy(device_, indices.transfer_family.value(), staging_buffer, vertex_buffer_, size_buffer);
|
||||||
|
|
||||||
vkFreeMemory(device_, staging_buffer_memory, nullptr);
|
vkFreeMemory(device_, staging_buffer_memory, nullptr);
|
||||||
vkDestroyBuffer(device_, staging_buffer, nullptr);
|
vkDestroyBuffer(device_, staging_buffer, nullptr);
|
||||||
@@ -845,11 +750,12 @@ void UwURenderEngine::allocate_index_buffer()
|
|||||||
std::vector<uint32_t> arr_indices = get_unique_family_indices(indices);
|
std::vector<uint32_t> arr_indices = get_unique_family_indices(indices);
|
||||||
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
|
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
|
||||||
|
|
||||||
VkBuffer staging_buffer = VK_NULL_HANDLE;
|
|
||||||
VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
|
|
||||||
VkDeviceSize size_buffer = sizeof(indices_[0]) * indices_.size();
|
VkDeviceSize size_buffer = sizeof(indices_[0]) * indices_.size();
|
||||||
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index);
|
VkBuffer staging_buffer = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory);
|
transfer_index);
|
||||||
|
VkDeviceMemory staging_buffer_memory = DeviceFunctions::allocate_device_memory(
|
||||||
|
physical_device_, device_, staging_buffer,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0);
|
vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0);
|
||||||
|
|
||||||
void* data;
|
void* data;
|
||||||
@@ -857,61 +763,16 @@ void UwURenderEngine::allocate_index_buffer()
|
|||||||
memcpy(data, indices_.data(), size_buffer);
|
memcpy(data, indices_.data(), size_buffer);
|
||||||
vkUnmapMemory(device_, staging_buffer_memory);
|
vkUnmapMemory(device_, staging_buffer_memory);
|
||||||
|
|
||||||
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, &index_buffer_, arr_indices);
|
index_buffer_ = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, arr_indices);
|
||||||
allocate_memory(index_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &index_buffer_memory_);
|
index_buffer_memory_ = DeviceFunctions::allocate_device_memory(physical_device_, device_, index_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
vkBindBufferMemory(device_, index_buffer_, index_buffer_memory_, 0);
|
vkBindBufferMemory(device_, index_buffer_, index_buffer_memory_, 0);
|
||||||
|
|
||||||
copy_memory(staging_buffer, index_buffer_, size_buffer);
|
DeviceFunctions::device_memcpy(device_, indices.transfer_family.value(),staging_buffer, index_buffer_, size_buffer);
|
||||||
|
|
||||||
vkDestroyBuffer(device_, staging_buffer, nullptr);
|
vkDestroyBuffer(device_, staging_buffer, nullptr);
|
||||||
vkFreeMemory(device_, staging_buffer_memory, nullptr);
|
vkFreeMemory(device_, staging_buffer_memory, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::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 UwURenderEngine::allocate_command_buffers()
|
void UwURenderEngine::allocate_command_buffers()
|
||||||
{
|
{
|
||||||
command_buffers_.resize(swapchain_images_.size());
|
command_buffers_.resize(swapchain_images_.size());
|
||||||
@@ -922,7 +783,7 @@ void UwURenderEngine::allocate_command_buffers()
|
|||||||
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
command_buffer_allocate_info.commandBufferCount = static_cast<uint32_t>(command_buffers_.size());
|
command_buffer_allocate_info.commandBufferCount = static_cast<uint32_t>(command_buffers_.size());
|
||||||
|
|
||||||
VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, command_buffers_.data()));
|
VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, command_buffers_.data()))
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::create_sync_objects()
|
void UwURenderEngine::create_sync_objects()
|
||||||
@@ -940,9 +801,9 @@ void UwURenderEngine::create_sync_objects()
|
|||||||
|
|
||||||
for (size_t i = 0; i < swapchain_images_.size(); ++i)
|
for (size_t i = 0; i < swapchain_images_.size(); ++i)
|
||||||
{
|
{
|
||||||
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &image_available_semaphores_[i]));
|
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &image_available_semaphores_[i]))
|
||||||
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &render_finished_semaphores_[i]));
|
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &render_finished_semaphores_[i]))
|
||||||
VK_CHECK(vkCreateFence(device_, &fence_info, nullptr, &in_flight_fences_[i]));
|
VK_CHECK(vkCreateFence(device_, &fence_info, nullptr, &in_flight_fences_[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -950,7 +811,7 @@ void UwURenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint
|
|||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo command_buffer_begin_info{};
|
VkCommandBufferBeginInfo command_buffer_begin_info{};
|
||||||
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
VK_CHECK(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info));
|
VK_CHECK(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info))
|
||||||
|
|
||||||
constexpr VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
constexpr VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||||
VkRenderPassBeginInfo render_pass_begin_info{};
|
VkRenderPassBeginInfo render_pass_begin_info{};
|
||||||
@@ -990,7 +851,7 @@ void UwURenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint
|
|||||||
vkCmdDrawIndexed(command_buffer, static_cast<uint32_t>(indices_.size()), 1, 0, 0, 0);
|
vkCmdDrawIndexed(command_buffer, static_cast<uint32_t>(indices_.size()), 1, 0, 0, 0);
|
||||||
|
|
||||||
vkCmdEndRenderPass(command_buffer);
|
vkCmdEndRenderPass(command_buffer);
|
||||||
VK_CHECK(vkEndCommandBuffer(command_buffer));
|
VK_CHECK(vkEndCommandBuffer(command_buffer))
|
||||||
}
|
}
|
||||||
|
|
||||||
void UwURenderEngine::update_uniform_buffer(uint32_t current_frame)
|
void UwURenderEngine::update_uniform_buffer(uint32_t current_frame)
|
||||||
@@ -998,7 +859,7 @@ void UwURenderEngine::update_uniform_buffer(uint32_t current_frame)
|
|||||||
static auto start_time = std::chrono::high_resolution_clock::now();
|
static auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
auto current_time = std::chrono::high_resolution_clock::now();
|
auto current_time = std::chrono::high_resolution_clock::now();
|
||||||
float time = std::chrono::duration_cast<std::chrono::duration<float>>(current_time - start_time).count();
|
float time = std::chrono::duration_cast<std::chrono::duration<float>>(current_time - start_time).count();
|
||||||
UniformBufferObject ubo{};
|
UniformBufferObject ubo;
|
||||||
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.proj = glm::perspective(glm::radians(45.0f), static_cast<float>(swapchain_extent_.width) / static_cast<float>(swapchain_extent_.height), 0.1f, 256.0f);
|
ubo.proj = glm::perspective(glm::radians(45.0f), static_cast<float>(swapchain_extent_.width) / static_cast<float>(swapchain_extent_.height), 0.1f, 256.0f);
|
||||||
@@ -1030,7 +891,7 @@ void UwURenderEngine::draw_frame()
|
|||||||
submit_info.signalSemaphoreCount = 1;
|
submit_info.signalSemaphoreCount = 1;
|
||||||
submit_info.pSignalSemaphores = &render_finished_semaphores_[current_frame_];
|
submit_info.pSignalSemaphores = &render_finished_semaphores_[current_frame_];
|
||||||
|
|
||||||
VK_CHECK(vkQueueSubmit(graphics_queue_, 1, &submit_info, in_flight_fences_[current_frame_]));
|
VK_CHECK(vkQueueSubmit(graphics_queue_, 1, &submit_info, in_flight_fences_[current_frame_]))
|
||||||
|
|
||||||
VkPresentInfoKHR present_info{};
|
VkPresentInfoKHR present_info{};
|
||||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
@@ -1048,12 +909,11 @@ void UwURenderEngine::draw_frame()
|
|||||||
|
|
||||||
void UwURenderEngine::create_surface()
|
void UwURenderEngine::create_surface()
|
||||||
{
|
{
|
||||||
VK_CHECK(glfwCreateWindowSurface(instance_, get_window(), nullptr, &surface_));
|
VK_CHECK(glfwCreateWindowSurface(instance_, get_window(), nullptr, &surface_))
|
||||||
}
|
}
|
||||||
|
|
||||||
UwURenderEngine::UwURenderEngine(CoreInstance& core):
|
UwURenderEngine::UwURenderEngine(CoreInstance& core):
|
||||||
core_(core),
|
core_(core)
|
||||||
model_manager_(new ModelManager)
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
,debug_messenger_(nullptr)
|
,debug_messenger_(nullptr)
|
||||||
#endif
|
#endif
|
||||||
@@ -1076,6 +936,8 @@ model_manager_(new ModelManager)
|
|||||||
allocate_command_buffers();
|
allocate_command_buffers();
|
||||||
allocate_index_buffer();
|
allocate_index_buffer();
|
||||||
create_sync_objects();
|
create_sync_objects();
|
||||||
|
|
||||||
|
model_manager_.reset(new ModelManager(physical_device_, device_));
|
||||||
}
|
}
|
||||||
|
|
||||||
UwURenderEngine::~UwURenderEngine()
|
UwURenderEngine::~UwURenderEngine()
|
||||||
|
|||||||
@@ -12,13 +12,6 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
#include <assert.h>
|
|
||||||
#define VK_CHECK(res) assert(res == VK_SUCCESS)
|
|
||||||
#else
|
|
||||||
#define VK_CHECK(res) if ((res) != VK_SUCCESS) throw std::runtime_error("Vulkan error: " + std::to_string(res))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class UwURenderEngine : public RenderEngineBase
|
class UwURenderEngine : public RenderEngineBase
|
||||||
{
|
{
|
||||||
struct QueueFamilyIndices
|
struct QueueFamilyIndices
|
||||||
@@ -33,20 +26,13 @@ class UwURenderEngine : public RenderEngineBase
|
|||||||
std::vector<VkSurfaceFormatKHR> formats;
|
std::vector<VkSurfaceFormatKHR> formats;
|
||||||
std::vector<VkPresentModeKHR> present_modes;
|
std::vector<VkPresentModeKHR> present_modes;
|
||||||
};
|
};
|
||||||
struct Vertex
|
|
||||||
{
|
|
||||||
glm::vec3 pos;
|
|
||||||
glm::vec3 color;
|
|
||||||
static VkVertexInputBindingDescription get_binding_description();
|
|
||||||
static std::array<VkVertexInputAttributeDescription, 2> get_vertex_attribute_descriptions();
|
|
||||||
};
|
|
||||||
struct UniformBufferObject {
|
struct UniformBufferObject {
|
||||||
glm::mat4 model;
|
glm::mat4 model;
|
||||||
glm::mat4 view;
|
glm::mat4 view;
|
||||||
glm::mat4 proj;
|
glm::mat4 proj;
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<Vertex> vertices_ = {
|
const std::vector<ModelManager::Vertex> vertices_ = {
|
||||||
{{-0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
|
{{-0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||||
{{0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
|
{{0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||||
{{0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
{{0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||||
@@ -117,13 +103,8 @@ class UwURenderEngine : public RenderEngineBase
|
|||||||
static QueueFamilyIndices find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface);
|
static QueueFamilyIndices find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface);
|
||||||
static VkSurfaceFormatKHR choose_surface_format(const std::vector<VkSurfaceFormatKHR>& surface_formats);
|
static VkSurfaceFormatKHR choose_surface_format(const std::vector<VkSurfaceFormatKHR>& surface_formats);
|
||||||
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);
|
|
||||||
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,
|
static std::vector<uint32_t> get_unique_family_indices(const QueueFamilyIndices& indices);
|
||||||
VkBuffer* buffer, const std::vector<uint32_t>& queue_families);
|
|
||||||
void allocate_memory(VkBuffer buffer, VkMemoryPropertyFlags property, VkDeviceMemory* device_memory);
|
|
||||||
uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
|
|
||||||
std::vector<uint32_t> get_unique_family_indices(const QueueFamilyIndices& indices);
|
|
||||||
|
|
||||||
void create_instance();
|
void create_instance();
|
||||||
void create_surface();
|
void create_surface();
|
||||||
@@ -144,7 +125,6 @@ class UwURenderEngine : public RenderEngineBase
|
|||||||
void allocate_vertex_buffer();
|
void allocate_vertex_buffer();
|
||||||
void allocate_index_buffer();
|
void allocate_index_buffer();
|
||||||
|
|
||||||
void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
|
||||||
void record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index) const;
|
void record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index) const;
|
||||||
void update_uniform_buffer(uint32_t current_frame);
|
void update_uniform_buffer(uint32_t current_frame);
|
||||||
void draw_frame();
|
void draw_frame();
|
||||||
|
|||||||
Reference in New Issue
Block a user