16.Index and Staging Buffers
This commit is contained in:
parent
6733eb3495
commit
633e6e5105
BIN
VulkanTest
BIN
VulkanTest
Binary file not shown.
|
|
@ -70,62 +70,53 @@ namespace hk
|
|||
// temporary helper function, creates a 1x1x1 cube centered at offset
|
||||
std::unique_ptr<Model> createCubeModel(hk::Device &device, glm::vec3 offset)
|
||||
{
|
||||
std::vector<Model::Vertex> vertices{
|
||||
|
||||
Model::Builder modelBuilder{};
|
||||
modelBuilder.vertices = {
|
||||
// left face (white)
|
||||
{{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}},
|
||||
{{-.5f, .5f, .5f}, {.9f, .9f, .9f}},
|
||||
{{-.5f, -.5f, .5f}, {.9f, .9f, .9f}},
|
||||
{{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}},
|
||||
{{-.5f, .5f, -.5f}, {.9f, .9f, .9f}},
|
||||
{{-.5f, .5f, .5f}, {.9f, .9f, .9f}},
|
||||
|
||||
// right face (yellow)
|
||||
{{.5f, -.5f, -.5f}, {.8f, .8f, .1f}},
|
||||
{{.5f, .5f, .5f}, {.8f, .8f, .1f}},
|
||||
{{.5f, -.5f, .5f}, {.8f, .8f, .1f}},
|
||||
{{.5f, -.5f, -.5f}, {.8f, .8f, .1f}},
|
||||
{{.5f, .5f, -.5f}, {.8f, .8f, .1f}},
|
||||
{{.5f, .5f, .5f}, {.8f, .8f, .1f}},
|
||||
|
||||
// top face (orange, remember y axis points down)
|
||||
{{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}},
|
||||
{{.5f, -.5f, .5f}, {.9f, .6f, .1f}},
|
||||
{{-.5f, -.5f, .5f}, {.9f, .6f, .1f}},
|
||||
{{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}},
|
||||
{{.5f, -.5f, -.5f}, {.9f, .6f, .1f}},
|
||||
{{.5f, -.5f, .5f}, {.9f, .6f, .1f}},
|
||||
|
||||
// bottom face (red)
|
||||
{{-.5f, .5f, -.5f}, {.8f, .1f, .1f}},
|
||||
{{.5f, .5f, .5f}, {.8f, .1f, .1f}},
|
||||
{{-.5f, .5f, .5f}, {.8f, .1f, .1f}},
|
||||
{{-.5f, .5f, -.5f}, {.8f, .1f, .1f}},
|
||||
{{.5f, .5f, -.5f}, {.8f, .1f, .1f}},
|
||||
{{.5f, .5f, .5f}, {.8f, .1f, .1f}},
|
||||
|
||||
// nose face (blue)
|
||||
{{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}},
|
||||
{{.5f, .5f, 0.5f}, {.1f, .1f, .8f}},
|
||||
{{-.5f, .5f, 0.5f}, {.1f, .1f, .8f}},
|
||||
{{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}},
|
||||
{{.5f, -.5f, 0.5f}, {.1f, .1f, .8f}},
|
||||
{{.5f, .5f, 0.5f}, {.1f, .1f, .8f}},
|
||||
|
||||
// tail face (green)
|
||||
{{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}},
|
||||
{{.5f, .5f, -0.5f}, {.1f, .8f, .1f}},
|
||||
{{-.5f, .5f, -0.5f}, {.1f, .8f, .1f}},
|
||||
{{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}},
|
||||
{{.5f, -.5f, -0.5f}, {.1f, .8f, .1f}},
|
||||
{{.5f, .5f, -0.5f}, {.1f, .8f, .1f}},
|
||||
|
||||
};
|
||||
for (auto &v : vertices)
|
||||
for (auto &v : modelBuilder.vertices)
|
||||
{
|
||||
v.position += offset;
|
||||
}
|
||||
return std::make_unique<Model>(device, vertices);
|
||||
|
||||
modelBuilder.indices = {0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 8, 11, 9,
|
||||
12, 13, 14, 12, 15, 13, 16, 17, 18, 16, 19, 17, 20, 21, 22, 20, 23, 21};
|
||||
|
||||
return std::make_unique<Model>(device, modelBuilder);
|
||||
}
|
||||
|
||||
void FirstApp::loadGameObjects()
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace hk
|
|||
}
|
||||
|
||||
// class member functions
|
||||
Device::Device(Window &window) : window{window}
|
||||
Device::Device(Window &window) : m_window{window}
|
||||
{
|
||||
createInstance();
|
||||
setupDebugMessenger();
|
||||
|
|
@ -67,16 +67,16 @@ namespace hk
|
|||
|
||||
Device::~Device()
|
||||
{
|
||||
vkDestroyCommandPool(device_, commandPool, nullptr);
|
||||
vkDestroyDevice(device_, nullptr);
|
||||
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
|
||||
vkDestroyDevice(m_device, nullptr);
|
||||
|
||||
if (enableValidationLayers)
|
||||
{
|
||||
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
|
||||
DestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr);
|
||||
}
|
||||
|
||||
vkDestroySurfaceKHR(instance, surface_, nullptr);
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
|
||||
vkDestroyInstance(m_instance, nullptr);
|
||||
}
|
||||
|
||||
void Device::createInstance()
|
||||
|
|
@ -118,7 +118,7 @@ namespace hk
|
|||
createInfo.pNext = nullptr;
|
||||
}
|
||||
|
||||
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
|
||||
if (vkCreateInstance(&createInfo, nullptr, &m_instance) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create instance!");
|
||||
}
|
||||
|
|
@ -129,36 +129,36 @@ namespace hk
|
|||
void Device::pickPhysicalDevice()
|
||||
{
|
||||
uint32_t deviceCount = 0;
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||
vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
|
||||
if (deviceCount == 0)
|
||||
{
|
||||
throw std::runtime_error("failed to find GPUs with Vulkan support!");
|
||||
}
|
||||
std::cout << "Device count: " << deviceCount << std::endl;
|
||||
std::vector<VkPhysicalDevice> devices(deviceCount);
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
|
||||
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
||||
|
||||
for (const auto &device : devices)
|
||||
{
|
||||
if (isDeviceSuitable(device))
|
||||
{
|
||||
physicalDevice = device;
|
||||
m_physicalDevice = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (physicalDevice == VK_NULL_HANDLE)
|
||||
if (m_physicalDevice == VK_NULL_HANDLE)
|
||||
{
|
||||
throw std::runtime_error("failed to find a suitable GPU!");
|
||||
}
|
||||
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
|
||||
vkGetPhysicalDeviceProperties(m_physicalDevice, &properties);
|
||||
std::cout << "physical device: " << properties.deviceName << std::endl;
|
||||
}
|
||||
|
||||
void Device::createLogicalDevice()
|
||||
{
|
||||
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
|
||||
QueueFamilyIndices indices = findQueueFamilies(m_physicalDevice);
|
||||
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily};
|
||||
|
|
@ -186,13 +186,13 @@ namespace hk
|
|||
createInfo.pEnabledFeatures = &deviceFeatures;
|
||||
|
||||
// Add device extensions, including portability subset if available (needed for MoltenVK)
|
||||
std::vector<const char*> enabledExtensions(deviceExtensions.begin(), deviceExtensions.end());
|
||||
std::vector<const char *> enabledExtensions(deviceExtensions.begin(), deviceExtensions.end());
|
||||
|
||||
// Check if VK_KHR_portability_subset is available and add it if needed
|
||||
uint32_t extensionCount;
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
|
||||
vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extensionCount, nullptr);
|
||||
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data());
|
||||
vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extensionCount, availableExtensions.data());
|
||||
|
||||
for (const auto &extension : availableExtensions)
|
||||
{
|
||||
|
|
@ -218,13 +218,13 @@ namespace hk
|
|||
createInfo.enabledLayerCount = 0;
|
||||
}
|
||||
|
||||
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device_) != VK_SUCCESS)
|
||||
if (vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create logical device!");
|
||||
}
|
||||
|
||||
vkGetDeviceQueue(device_, indices.graphicsFamily, 0, &graphicsQueue_);
|
||||
vkGetDeviceQueue(device_, indices.presentFamily, 0, &presentQueue_);
|
||||
vkGetDeviceQueue(m_device, indices.graphicsFamily, 0, &m_graphicsQueue);
|
||||
vkGetDeviceQueue(m_device, indices.presentFamily, 0, &m_presentQueue);
|
||||
}
|
||||
|
||||
void Device::createCommandPool()
|
||||
|
|
@ -237,13 +237,13 @@ namespace hk
|
|||
poolInfo.flags =
|
||||
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
|
||||
if (vkCreateCommandPool(device_, &poolInfo, nullptr, &commandPool) != VK_SUCCESS)
|
||||
if (vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create command pool!");
|
||||
}
|
||||
}
|
||||
|
||||
void Device::createSurface() { window.createWindowSurface(instance, &surface_); }
|
||||
void Device::createSurface() { m_window.createWindowSurface(m_instance, &m_surface); }
|
||||
|
||||
bool Device::isDeviceSuitable(VkPhysicalDevice device)
|
||||
{
|
||||
|
|
@ -285,7 +285,7 @@ namespace hk
|
|||
return;
|
||||
VkDebugUtilsMessengerCreateInfoEXT createInfo;
|
||||
populateDebugMessengerCreateInfo(createInfo);
|
||||
if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS)
|
||||
if (CreateDebugUtilsMessengerEXT(m_instance, &createInfo, nullptr, &m_debugMessenger) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to set up debug messenger!");
|
||||
}
|
||||
|
|
@ -408,7 +408,7 @@ namespace hk
|
|||
indices.graphicsFamilyHasValue = true;
|
||||
}
|
||||
VkBool32 presentSupport = false;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface_, &presentSupport);
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport);
|
||||
if (queueFamily.queueCount > 0 && presentSupport)
|
||||
{
|
||||
indices.presentFamily = i;
|
||||
|
|
@ -428,26 +428,26 @@ namespace hk
|
|||
SwapChainSupportDetails Device::querySwapChainSupport(VkPhysicalDevice device)
|
||||
{
|
||||
SwapChainSupportDetails details;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.capabilities);
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities);
|
||||
|
||||
uint32_t formatCount;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, nullptr);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr);
|
||||
|
||||
if (formatCount != 0)
|
||||
{
|
||||
details.formats.resize(formatCount);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, details.formats.data());
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data());
|
||||
}
|
||||
|
||||
uint32_t presentModeCount;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, nullptr);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr);
|
||||
|
||||
if (presentModeCount != 0)
|
||||
{
|
||||
details.presentModes.resize(presentModeCount);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(
|
||||
device,
|
||||
surface_,
|
||||
m_surface,
|
||||
&presentModeCount,
|
||||
details.presentModes.data());
|
||||
}
|
||||
|
|
@ -460,7 +460,7 @@ namespace hk
|
|||
for (VkFormat format : candidates)
|
||||
{
|
||||
VkFormatProperties props;
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);
|
||||
vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &props);
|
||||
|
||||
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features)
|
||||
{
|
||||
|
|
@ -478,7 +478,7 @@ namespace hk
|
|||
uint32_t Device::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
|
||||
vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memProperties);
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
|
||||
{
|
||||
if ((typeFilter & (1 << i)) &&
|
||||
|
|
@ -504,25 +504,25 @@ namespace hk
|
|||
bufferInfo.usage = usage;
|
||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
if (vkCreateBuffer(device_, &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
||||
if (vkCreateBuffer(m_device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create vertex buffer!");
|
||||
}
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetBufferMemoryRequirements(device_, buffer, &memRequirements);
|
||||
vkGetBufferMemoryRequirements(m_device, buffer, &memRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
|
||||
|
||||
if (vkAllocateMemory(device_, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS)
|
||||
if (vkAllocateMemory(m_device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to allocate vertex buffer memory!");
|
||||
}
|
||||
|
||||
vkBindBufferMemory(device_, buffer, bufferMemory, 0);
|
||||
vkBindBufferMemory(m_device, buffer, bufferMemory, 0);
|
||||
}
|
||||
|
||||
VkCommandBuffer Device::beginSingleTimeCommands()
|
||||
|
|
@ -530,11 +530,11 @@ namespace hk
|
|||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandPool = commandPool;
|
||||
allocInfo.commandPool = m_commandPool;
|
||||
allocInfo.commandBufferCount = 1;
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
vkAllocateCommandBuffers(device_, &allocInfo, &commandBuffer);
|
||||
vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
|
|
@ -553,10 +553,10 @@ namespace hk
|
|||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &commandBuffer;
|
||||
|
||||
vkQueueSubmit(graphicsQueue_, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(graphicsQueue_);
|
||||
vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(m_graphicsQueue);
|
||||
|
||||
vkFreeCommandBuffers(device_, commandPool, 1, &commandBuffer);
|
||||
vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
|
||||
}
|
||||
|
||||
void Device::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
|
||||
|
|
@ -606,25 +606,25 @@ namespace hk
|
|||
VkImage &image,
|
||||
VkDeviceMemory &imageMemory)
|
||||
{
|
||||
if (vkCreateImage(device_, &imageInfo, nullptr, &image) != VK_SUCCESS)
|
||||
if (vkCreateImage(m_device, &imageInfo, nullptr, &image) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create image!");
|
||||
}
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetImageMemoryRequirements(device_, image, &memRequirements);
|
||||
vkGetImageMemoryRequirements(m_device, image, &memRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
|
||||
|
||||
if (vkAllocateMemory(device_, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
|
||||
if (vkAllocateMemory(m_device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to allocate image memory!");
|
||||
}
|
||||
|
||||
if (vkBindImageMemory(device_, image, imageMemory, 0) != VK_SUCCESS)
|
||||
if (vkBindImageMemory(m_device, image, imageMemory, 0) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to bind image memory!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,15 +43,15 @@ namespace hk
|
|||
Device(Device &&) = delete;
|
||||
Device &operator=(Device &&) = delete;
|
||||
|
||||
VkCommandPool getCommandPool() { return commandPool; }
|
||||
VkDevice device() { return device_; }
|
||||
VkSurfaceKHR surface() { return surface_; }
|
||||
VkQueue graphicsQueue() { return graphicsQueue_; }
|
||||
VkQueue presentQueue() { return presentQueue_; }
|
||||
VkCommandPool getCommandPool() { return m_commandPool; }
|
||||
VkDevice device() { return m_device; }
|
||||
VkSurfaceKHR surface() { return m_surface; }
|
||||
VkQueue graphicsQueue() { return m_graphicsQueue; }
|
||||
VkQueue presentQueue() { return m_presentQueue; }
|
||||
|
||||
SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(physicalDevice); }
|
||||
SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(m_physicalDevice); }
|
||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
QueueFamilyIndices findPhysicalQueueFamilies() { return findQueueFamilies(physicalDevice); }
|
||||
QueueFamilyIndices findPhysicalQueueFamilies() { return findQueueFamilies(m_physicalDevice); }
|
||||
VkFormat findSupportedFormat(
|
||||
const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
|
||||
|
||||
|
|
@ -94,16 +94,16 @@ namespace hk
|
|||
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
|
||||
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
|
||||
|
||||
VkInstance instance;
|
||||
VkDebugUtilsMessengerEXT debugMessenger;
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
Window &window;
|
||||
VkCommandPool commandPool;
|
||||
VkInstance m_instance;
|
||||
VkDebugUtilsMessengerEXT m_debugMessenger;
|
||||
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
||||
Window &m_window;
|
||||
VkCommandPool m_commandPool;
|
||||
|
||||
VkDevice device_;
|
||||
VkSurfaceKHR surface_;
|
||||
VkQueue graphicsQueue_;
|
||||
VkQueue presentQueue_;
|
||||
VkDevice m_device;
|
||||
VkSurfaceKHR m_surface;
|
||||
VkQueue m_graphicsQueue;
|
||||
VkQueue m_presentQueue;
|
||||
|
||||
const std::vector<const char *> validationLayers = {"VK_LAYER_KHRONOS_validation"};
|
||||
const std::vector<const char *> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||
|
|
|
|||
99
hk_model.cpp
99
hk_model.cpp
|
|
@ -4,45 +4,112 @@
|
|||
#include <cstring>
|
||||
|
||||
namespace hk{
|
||||
Model::Model(Device &device, const std::vector<Vertex> &vertices)
|
||||
: device{device}
|
||||
Model::Model(Device &device, const Builder &builder)
|
||||
: m_device{device}
|
||||
{
|
||||
createVertexBuffers(vertices);
|
||||
createVertexBuffers(builder.vertices);
|
||||
createIndexBuffers(builder.indices);
|
||||
}
|
||||
|
||||
Model::~Model()
|
||||
{
|
||||
vkDestroyBuffer(device.device(), vertexBuffer, nullptr);
|
||||
vkFreeMemory(device.device(), vertexBufferMemory, nullptr);
|
||||
vkDestroyBuffer(m_device.device(), m_vertexBuffer, nullptr);
|
||||
vkFreeMemory(m_device.device(), m_vertexBufferMemory, nullptr);
|
||||
vkDestroyBuffer(m_device.device(), m_indexBuffer, nullptr);
|
||||
vkFreeMemory(m_device.device(), m_indexBufferMemory, nullptr);
|
||||
}
|
||||
|
||||
void Model::createVertexBuffers(const std::vector<Vertex> &vertices)
|
||||
{
|
||||
vertexCount = static_cast<uint32_t>(vertices.size());
|
||||
assert(vertexCount >= 3 && "Vertex count must be at least 3");
|
||||
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount;
|
||||
device.createBuffer(
|
||||
m_vertexCount = static_cast<uint32_t>(vertices.size());
|
||||
assert(m_vertexCount >= 3 && "Vertex count must be at least 3");
|
||||
VkDeviceSize bufferSize = sizeof(vertices[0]) * m_vertexCount;
|
||||
|
||||
VkBuffer stagingBuffer;
|
||||
VkDeviceMemory stagingBufferMemory;
|
||||
m_device.createBuffer(
|
||||
bufferSize,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
vertexBuffer,
|
||||
vertexBufferMemory
|
||||
stagingBuffer,
|
||||
stagingBufferMemory
|
||||
);
|
||||
void *data;
|
||||
vkMapMemory(device.device(), vertexBufferMemory, 0, bufferSize, 0, &data);
|
||||
vkMapMemory(m_device.device(), stagingBufferMemory, 0, bufferSize, 0, &data);
|
||||
memcpy(data, vertices.data(), static_cast<size_t>(bufferSize));
|
||||
vkUnmapMemory(device.device(), vertexBufferMemory);
|
||||
vkUnmapMemory(m_device.device(), stagingBufferMemory);
|
||||
|
||||
m_device.createBuffer(
|
||||
bufferSize,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
m_vertexBuffer,
|
||||
m_vertexBufferMemory
|
||||
);
|
||||
m_device.copyBuffer(stagingBuffer, m_vertexBuffer, bufferSize);
|
||||
|
||||
vkDestroyBuffer(m_device.device(), stagingBuffer, nullptr);
|
||||
vkFreeMemory(m_device.device(), stagingBufferMemory, nullptr);
|
||||
}
|
||||
|
||||
void Model::createIndexBuffers(const std::vector<uint32_t> &indices)
|
||||
{
|
||||
m_indexCount = static_cast<uint32_t>(indices.size());
|
||||
m_hasIndexBuffer = m_indexCount > 0;
|
||||
|
||||
if (!m_hasIndexBuffer)
|
||||
return;
|
||||
|
||||
VkDeviceSize bufferSize = sizeof(indices[0]) * m_indexCount;
|
||||
|
||||
VkBuffer stagingBuffer;
|
||||
VkDeviceMemory stagingBufferMemory;
|
||||
m_device.createBuffer(
|
||||
bufferSize,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
stagingBuffer,
|
||||
stagingBufferMemory
|
||||
);
|
||||
void *data;
|
||||
vkMapMemory(m_device.device(), stagingBufferMemory, 0, bufferSize, 0, &data);
|
||||
memcpy(data, indices.data(), static_cast<size_t>(bufferSize));
|
||||
vkUnmapMemory(m_device.device(), stagingBufferMemory);
|
||||
|
||||
m_device.createBuffer(
|
||||
bufferSize,
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
m_indexBuffer,
|
||||
m_indexBufferMemory
|
||||
);
|
||||
m_device.copyBuffer(stagingBuffer, m_indexBuffer, bufferSize);
|
||||
|
||||
vkDestroyBuffer(m_device.device(), stagingBuffer, nullptr);
|
||||
vkFreeMemory(m_device.device(), stagingBufferMemory, nullptr);
|
||||
}
|
||||
|
||||
void Model::bind(VkCommandBuffer commandBuffer)
|
||||
{
|
||||
VkBuffer buffers[] = {vertexBuffer};
|
||||
VkBuffer buffers[] = {m_vertexBuffer};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
|
||||
|
||||
if (m_hasIndexBuffer)
|
||||
{
|
||||
vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
}
|
||||
void Model::draw(VkCommandBuffer commandBuffer)
|
||||
{
|
||||
vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0);
|
||||
if (m_hasIndexBuffer)
|
||||
{
|
||||
vkCmdDrawIndexed(commandBuffer, m_indexCount, 1, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vkCmdDraw(commandBuffer, m_vertexCount, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<VkVertexInputBindingDescription> Model::Vertex::getBindingDescriptions()
|
||||
|
|
|
|||
22
hk_model.hpp
22
hk_model.hpp
|
|
@ -20,7 +20,13 @@ namespace hk{
|
|||
static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();
|
||||
};
|
||||
|
||||
Model(Device &device, const std::vector<Vertex> &vertices);
|
||||
struct Builder
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
};
|
||||
|
||||
Model(Device &device, const Builder &builder);
|
||||
~Model();
|
||||
|
||||
Model(const Model &) = delete;
|
||||
|
|
@ -30,10 +36,16 @@ namespace hk{
|
|||
void draw(VkCommandBuffer commandBuffer);
|
||||
private:
|
||||
void createVertexBuffers(const std::vector<Vertex> &vertices);
|
||||
void createIndexBuffers(const std::vector<uint32_t> &indices);
|
||||
|
||||
Device &device;
|
||||
VkBuffer vertexBuffer;
|
||||
VkDeviceMemory vertexBufferMemory;
|
||||
uint32_t vertexCount;
|
||||
Device &m_device;
|
||||
VkBuffer m_vertexBuffer;
|
||||
VkDeviceMemory m_vertexBufferMemory;
|
||||
uint32_t m_vertexCount;
|
||||
|
||||
bool m_hasIndexBuffer = false;
|
||||
VkBuffer m_indexBuffer;
|
||||
VkDeviceMemory m_indexBufferMemory;
|
||||
uint32_t m_indexCount;
|
||||
};
|
||||
}
|
||||
|
|
@ -14,21 +14,21 @@ namespace hk
|
|||
Device& device,
|
||||
const std::string &vertFilePath,
|
||||
const std::string &fragFilePath,
|
||||
const PipelineConfigInfo& configInfo) : device(device)
|
||||
const PipelineConfigInfo& configInfo) : m_device(device)
|
||||
{
|
||||
createGraphicPipeline(vertFilePath, fragFilePath, configInfo);
|
||||
}
|
||||
|
||||
Pipeline::~Pipeline()
|
||||
{
|
||||
vkDestroyShaderModule(device.device(), vertShaderModule, nullptr);
|
||||
vkDestroyShaderModule(device.device(), fragShaderModule, nullptr);
|
||||
vkDestroyPipeline(device.device(), graphicPipeline, nullptr);
|
||||
vkDestroyShaderModule(m_device.device(), m_vertShaderModule, nullptr);
|
||||
vkDestroyShaderModule(m_device.device(), m_fragShaderModule, nullptr);
|
||||
vkDestroyPipeline(m_device.device(), m_graphicPipeline, nullptr);
|
||||
}
|
||||
|
||||
void Pipeline::bind(VkCommandBuffer commandBuffer)
|
||||
{
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicPipeline);
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicPipeline);
|
||||
}
|
||||
|
||||
void Pipeline::defaultPipelineConfigInfo(PipelineConfigInfo& configInfo)
|
||||
|
|
@ -134,13 +134,13 @@ namespace hk
|
|||
std::vector<char> vertCode = readFile(vertFilePath);
|
||||
std::vector<char> fragCode = readFile(fragFilePath);
|
||||
|
||||
createShaderModule(vertCode, &vertShaderModule);
|
||||
createShaderModule(fragCode, &fragShaderModule);
|
||||
createShaderModule(vertCode, &m_vertShaderModule);
|
||||
createShaderModule(fragCode, &m_fragShaderModule);
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaderStages[2];
|
||||
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
shaderStages[0].module = vertShaderModule;
|
||||
shaderStages[0].module = m_vertShaderModule;
|
||||
shaderStages[0].pName = "main";
|
||||
shaderStages[0].flags = 0;
|
||||
shaderStages[0].pNext = nullptr;
|
||||
|
|
@ -148,7 +148,7 @@ namespace hk
|
|||
|
||||
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shaderStages[1].module = fragShaderModule;
|
||||
shaderStages[1].module = m_fragShaderModule;
|
||||
shaderStages[1].pName = "main";
|
||||
shaderStages[1].flags = 0;
|
||||
shaderStages[1].pNext = nullptr;
|
||||
|
|
@ -184,7 +184,7 @@ namespace hk
|
|||
pipelineInfo.basePipelineIndex = -1;
|
||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
|
||||
if (vkCreateGraphicsPipelines(device.device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicPipeline) != VK_SUCCESS)
|
||||
if (vkCreateGraphicsPipelines(m_device.device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_graphicPipeline) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create graphics pipeline!");
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ namespace hk
|
|||
createInfo.codeSize = code.size();
|
||||
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
|
||||
|
||||
if (vkCreateShaderModule(device.device(), &createInfo, nullptr, shaderModule) != VK_SUCCESS)
|
||||
if (vkCreateShaderModule(m_device.device(), &createInfo, nullptr, shaderModule) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create shader module!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ namespace hk
|
|||
|
||||
void createShaderModule(const std::vector<char>& code, VkShaderModule* shaderModule);
|
||||
|
||||
Device& device;
|
||||
VkPipeline graphicPipeline;
|
||||
VkShaderModule vertShaderModule;
|
||||
VkShaderModule fragShaderModule;
|
||||
Device& m_device;
|
||||
VkPipeline m_graphicPipeline;
|
||||
VkShaderModule m_vertShaderModule;
|
||||
VkShaderModule m_fragShaderModule;
|
||||
};
|
||||
}
|
||||
|
|
@ -13,19 +13,19 @@ namespace hk
|
|||
{
|
||||
|
||||
SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent)
|
||||
: device{deviceRef}, windowExtent{extent}
|
||||
: m_device{deviceRef}, m_windowExtent{extent}
|
||||
{
|
||||
init();
|
||||
}
|
||||
SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent, std::shared_ptr<SwapChain> previous)
|
||||
: device{deviceRef}, windowExtent{extent}, oldSwapChain{previous}
|
||||
: m_device{deviceRef}, m_windowExtent{extent}, m_oldSwapChain{previous}
|
||||
{
|
||||
init();
|
||||
// Reset currentFrame to 0 when creating a new swap chain
|
||||
currentFrame = 0;
|
||||
m_currentFrame = 0;
|
||||
|
||||
// clean up old swap chain
|
||||
oldSwapChain = nullptr;
|
||||
m_oldSwapChain = nullptr;
|
||||
}
|
||||
|
||||
void SwapChain::init()
|
||||
|
|
@ -40,59 +40,59 @@ namespace hk
|
|||
|
||||
SwapChain::~SwapChain()
|
||||
{
|
||||
for (auto imageView : swapChainImageViews)
|
||||
for (auto imageView : m_swapChainImageViews)
|
||||
{
|
||||
vkDestroyImageView(device.device(), imageView, nullptr);
|
||||
vkDestroyImageView(m_device.device(), imageView, nullptr);
|
||||
}
|
||||
swapChainImageViews.clear();
|
||||
m_swapChainImageViews.clear();
|
||||
|
||||
if (swapChain != nullptr)
|
||||
if (m_swapChain != nullptr)
|
||||
{
|
||||
vkDestroySwapchainKHR(device.device(), swapChain, nullptr);
|
||||
swapChain = nullptr;
|
||||
vkDestroySwapchainKHR(m_device.device(), m_swapChain, nullptr);
|
||||
m_swapChain = nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < depthImages.size(); i++)
|
||||
for (int i = 0; i < m_depthImages.size(); i++)
|
||||
{
|
||||
vkDestroyImageView(device.device(), depthImageViews[i], nullptr);
|
||||
vkDestroyImage(device.device(), depthImages[i], nullptr);
|
||||
vkFreeMemory(device.device(), depthImageMemorys[i], nullptr);
|
||||
vkDestroyImageView(m_device.device(), m_depthImageViews[i], nullptr);
|
||||
vkDestroyImage(m_device.device(), m_depthImages[i], nullptr);
|
||||
vkFreeMemory(m_device.device(), m_depthImageMemorys[i], nullptr);
|
||||
}
|
||||
|
||||
for (auto framebuffer : swapChainFramebuffers)
|
||||
for (auto framebuffer : m_swapChainFramebuffers)
|
||||
{
|
||||
vkDestroyFramebuffer(device.device(), framebuffer, nullptr);
|
||||
vkDestroyFramebuffer(m_device.device(), framebuffer, nullptr);
|
||||
}
|
||||
|
||||
vkDestroyRenderPass(device.device(), renderPass, nullptr);
|
||||
vkDestroyRenderPass(m_device.device(), m_renderPass, nullptr);
|
||||
|
||||
// cleanup synchronization objects
|
||||
for (size_t i = 0; i < imageAvailableSemaphores.size(); i++)
|
||||
for (size_t i = 0; i < m_imageAvailableSemaphores.size(); i++)
|
||||
{
|
||||
vkDestroySemaphore(device.device(), renderFinishedSemaphores[i], nullptr);
|
||||
vkDestroySemaphore(device.device(), imageAvailableSemaphores[i], nullptr);
|
||||
vkDestroySemaphore(m_device.device(), m_renderFinishedSemaphores[i], nullptr);
|
||||
vkDestroySemaphore(m_device.device(), m_imageAvailableSemaphores[i], nullptr);
|
||||
}
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
vkDestroyFence(device.device(), inFlightFences[i], nullptr);
|
||||
vkDestroyFence(m_device.device(), m_inFlightFences[i], nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
VkResult SwapChain::acquireNextImage(uint32_t *imageIndex)
|
||||
{
|
||||
vkWaitForFences(
|
||||
device.device(),
|
||||
m_device.device(),
|
||||
1,
|
||||
&inFlightFences[currentFrame],
|
||||
&m_inFlightFences[m_currentFrame],
|
||||
VK_TRUE,
|
||||
std::numeric_limits<uint64_t>::max());
|
||||
|
||||
// Acquire with a temporary semaphore, we'll use the imageIndex-specific one later
|
||||
VkResult result = vkAcquireNextImageKHR(
|
||||
device.device(),
|
||||
swapChain,
|
||||
m_device.device(),
|
||||
m_swapChain,
|
||||
std::numeric_limits<uint64_t>::max(),
|
||||
imageAvailableSemaphores[currentFrame % imageAvailableSemaphores.size()],
|
||||
m_imageAvailableSemaphores[m_currentFrame % m_imageAvailableSemaphores.size()],
|
||||
VK_NULL_HANDLE,
|
||||
imageIndex);
|
||||
|
||||
|
|
@ -102,17 +102,17 @@ namespace hk
|
|||
VkResult SwapChain::submitCommandBuffers(
|
||||
const VkCommandBuffer *buffers, uint32_t *imageIndex)
|
||||
{
|
||||
if (imagesInFlight[*imageIndex] != VK_NULL_HANDLE)
|
||||
if (m_imagesInFlight[*imageIndex] != VK_NULL_HANDLE)
|
||||
{
|
||||
vkWaitForFences(device.device(), 1, &imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX);
|
||||
vkWaitForFences(m_device.device(), 1, &m_imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX);
|
||||
}
|
||||
imagesInFlight[*imageIndex] = inFlightFences[currentFrame];
|
||||
m_imagesInFlight[*imageIndex] = m_inFlightFences[m_currentFrame];
|
||||
|
||||
VkSubmitInfo submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
// Use the semaphore associated with the currentFrame for waiting (from acquireNextImage)
|
||||
VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame % imageAvailableSemaphores.size()]};
|
||||
VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame % m_imageAvailableSemaphores.size()]};
|
||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||
|
|
@ -122,12 +122,12 @@ namespace hk
|
|||
submitInfo.pCommandBuffers = buffers;
|
||||
|
||||
// Use the semaphore associated with this specific image for signaling
|
||||
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[*imageIndex]};
|
||||
VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[*imageIndex]};
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||
|
||||
vkResetFences(device.device(), 1, &inFlightFences[currentFrame]);
|
||||
if (vkQueueSubmit(device.graphicsQueue(), 1, &submitInfo, inFlightFences[currentFrame]) !=
|
||||
vkResetFences(m_device.device(), 1, &m_inFlightFences[m_currentFrame]);
|
||||
if (vkQueueSubmit(m_device.graphicsQueue(), 1, &submitInfo, m_inFlightFences[m_currentFrame]) !=
|
||||
VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to submit draw command buffer!");
|
||||
|
|
@ -139,22 +139,22 @@ namespace hk
|
|||
presentInfo.waitSemaphoreCount = 1;
|
||||
presentInfo.pWaitSemaphores = signalSemaphores;
|
||||
|
||||
VkSwapchainKHR swapChains[] = {swapChain};
|
||||
VkSwapchainKHR swapChains[] = {m_swapChain};
|
||||
presentInfo.swapchainCount = 1;
|
||||
presentInfo.pSwapchains = swapChains;
|
||||
|
||||
presentInfo.pImageIndices = imageIndex;
|
||||
|
||||
auto result = vkQueuePresentKHR(device.presentQueue(), &presentInfo);
|
||||
auto result = vkQueuePresentKHR(m_device.presentQueue(), &presentInfo);
|
||||
|
||||
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SwapChain::createSwapChain()
|
||||
{
|
||||
SwapChainSupportDetails swapChainSupport = device.getSwapChainSupport();
|
||||
SwapChainSupportDetails swapChainSupport = m_device.getSwapChainSupport();
|
||||
|
||||
VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
|
||||
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
|
||||
|
|
@ -169,7 +169,7 @@ namespace hk
|
|||
|
||||
VkSwapchainCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
createInfo.surface = device.surface();
|
||||
createInfo.surface = m_device.surface();
|
||||
|
||||
createInfo.minImageCount = imageCount;
|
||||
createInfo.imageFormat = surfaceFormat.format;
|
||||
|
|
@ -178,7 +178,7 @@ namespace hk
|
|||
createInfo.imageArrayLayers = 1;
|
||||
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
QueueFamilyIndices indices = device.findPhysicalQueueFamilies();
|
||||
QueueFamilyIndices indices = m_device.findPhysicalQueueFamilies();
|
||||
uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily};
|
||||
|
||||
if (indices.graphicsFamily != indices.presentFamily)
|
||||
|
|
@ -200,9 +200,9 @@ namespace hk
|
|||
createInfo.presentMode = presentMode;
|
||||
createInfo.clipped = VK_TRUE;
|
||||
|
||||
createInfo.oldSwapchain = oldSwapChain == nullptr ? VK_NULL_HANDLE : oldSwapChain->swapChain;
|
||||
createInfo.oldSwapchain = m_oldSwapChain == nullptr ? VK_NULL_HANDLE : m_oldSwapChain->m_swapChain;
|
||||
|
||||
if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &swapChain) != VK_SUCCESS)
|
||||
if (vkCreateSwapchainKHR(m_device.device(), &createInfo, nullptr, &m_swapChain) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create swap chain!");
|
||||
}
|
||||
|
|
@ -211,31 +211,31 @@ namespace hk
|
|||
// allowed to create a swap chain with more. That's why we'll first query the final number of
|
||||
// images with vkGetSwapchainImagesKHR, then resize the container and finally call it again to
|
||||
// retrieve the handles.
|
||||
vkGetSwapchainImagesKHR(device.device(), swapChain, &imageCount, nullptr);
|
||||
swapChainImages.resize(imageCount);
|
||||
vkGetSwapchainImagesKHR(device.device(), swapChain, &imageCount, swapChainImages.data());
|
||||
vkGetSwapchainImagesKHR(m_device.device(), m_swapChain, &imageCount, nullptr);
|
||||
m_swapChainImages.resize(imageCount);
|
||||
vkGetSwapchainImagesKHR(m_device.device(), m_swapChain, &imageCount, m_swapChainImages.data());
|
||||
|
||||
swapChainImageFormat = surfaceFormat.format;
|
||||
swapChainExtent = extent;
|
||||
m_swapChainImageFormat = surfaceFormat.format;
|
||||
m_swapChainExtent = extent;
|
||||
}
|
||||
|
||||
void SwapChain::createImageViews()
|
||||
{
|
||||
swapChainImageViews.resize(swapChainImages.size());
|
||||
for (size_t i = 0; i < swapChainImages.size(); i++)
|
||||
m_swapChainImageViews.resize(m_swapChainImages.size());
|
||||
for (size_t i = 0; i < m_swapChainImages.size(); i++)
|
||||
{
|
||||
VkImageViewCreateInfo viewInfo{};
|
||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewInfo.image = swapChainImages[i];
|
||||
viewInfo.image = m_swapChainImages[i];
|
||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = swapChainImageFormat;
|
||||
viewInfo.format = m_swapChainImageFormat;
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||
viewInfo.subresourceRange.levelCount = 1;
|
||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
if (vkCreateImageView(device.device(), &viewInfo, nullptr, &swapChainImageViews[i]) !=
|
||||
if (vkCreateImageView(m_device.device(), &viewInfo, nullptr, &m_swapChainImageViews[i]) !=
|
||||
VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create texture image view!");
|
||||
|
|
@ -300,7 +300,7 @@ namespace hk
|
|||
renderPassInfo.dependencyCount = 1;
|
||||
renderPassInfo.pDependencies = &dependency;
|
||||
|
||||
if (vkCreateRenderPass(device.device(), &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS)
|
||||
if (vkCreateRenderPass(m_device.device(), &renderPassInfo, nullptr, &m_renderPass) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create render pass!");
|
||||
}
|
||||
|
|
@ -308,15 +308,15 @@ namespace hk
|
|||
|
||||
void SwapChain::createFramebuffers()
|
||||
{
|
||||
swapChainFramebuffers.resize(imageCount());
|
||||
m_swapChainFramebuffers.resize(imageCount());
|
||||
for (size_t i = 0; i < imageCount(); i++)
|
||||
{
|
||||
std::array<VkImageView, 2> attachments = {swapChainImageViews[i], depthImageViews[i]};
|
||||
std::array<VkImageView, 2> attachments = {m_swapChainImageViews[i], m_depthImageViews[i]};
|
||||
|
||||
VkExtent2D swapChainExtent = getSwapChainExtent();
|
||||
VkFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.renderPass = renderPass;
|
||||
framebufferInfo.renderPass = m_renderPass;
|
||||
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||
framebufferInfo.pAttachments = attachments.data();
|
||||
framebufferInfo.width = swapChainExtent.width;
|
||||
|
|
@ -324,10 +324,10 @@ namespace hk
|
|||
framebufferInfo.layers = 1;
|
||||
|
||||
if (vkCreateFramebuffer(
|
||||
device.device(),
|
||||
m_device.device(),
|
||||
&framebufferInfo,
|
||||
nullptr,
|
||||
&swapChainFramebuffers[i]) != VK_SUCCESS)
|
||||
&m_swapChainFramebuffers[i]) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create framebuffer!");
|
||||
}
|
||||
|
|
@ -337,14 +337,14 @@ namespace hk
|
|||
void SwapChain::createDepthResources()
|
||||
{
|
||||
VkFormat depthFormat = findDepthFormat();
|
||||
swapChainDepthFormat = depthFormat;
|
||||
m_swapChainDepthFormat = depthFormat;
|
||||
VkExtent2D swapChainExtent = getSwapChainExtent();
|
||||
|
||||
depthImages.resize(imageCount());
|
||||
depthImageMemorys.resize(imageCount());
|
||||
depthImageViews.resize(imageCount());
|
||||
m_depthImages.resize(imageCount());
|
||||
m_depthImageMemorys.resize(imageCount());
|
||||
m_depthImageViews.resize(imageCount());
|
||||
|
||||
for (int i = 0; i < depthImages.size(); i++)
|
||||
for (int i = 0; i < m_depthImages.size(); i++)
|
||||
{
|
||||
VkImageCreateInfo imageInfo{};
|
||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
|
|
@ -362,15 +362,15 @@ namespace hk
|
|||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imageInfo.flags = 0;
|
||||
|
||||
device.createImageWithInfo(
|
||||
m_device.createImageWithInfo(
|
||||
imageInfo,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
depthImages[i],
|
||||
depthImageMemorys[i]);
|
||||
m_depthImages[i],
|
||||
m_depthImageMemorys[i]);
|
||||
|
||||
VkImageViewCreateInfo viewInfo{};
|
||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewInfo.image = depthImages[i];
|
||||
viewInfo.image = m_depthImages[i];
|
||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = depthFormat;
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
|
@ -379,7 +379,7 @@ namespace hk
|
|||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
if (vkCreateImageView(device.device(), &viewInfo, nullptr, &depthImageViews[i]) != VK_SUCCESS)
|
||||
if (vkCreateImageView(m_device.device(), &viewInfo, nullptr, &m_depthImageViews[i]) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create texture image view!");
|
||||
}
|
||||
|
|
@ -389,10 +389,10 @@ namespace hk
|
|||
void SwapChain::createSyncObjects()
|
||||
{
|
||||
// Create one set of semaphores for each swapchain image
|
||||
imageAvailableSemaphores.resize(imageCount());
|
||||
renderFinishedSemaphores.resize(imageCount());
|
||||
inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
imagesInFlight.resize(imageCount(), VK_NULL_HANDLE);
|
||||
m_imageAvailableSemaphores.resize(imageCount());
|
||||
m_renderFinishedSemaphores.resize(imageCount());
|
||||
m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
m_imagesInFlight.resize(imageCount(), VK_NULL_HANDLE);
|
||||
|
||||
VkSemaphoreCreateInfo semaphoreInfo = {};
|
||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
|
@ -403,9 +403,9 @@ namespace hk
|
|||
|
||||
for (size_t i = 0; i < imageCount(); i++)
|
||||
{
|
||||
if (vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) !=
|
||||
if (vkCreateSemaphore(m_device.device(), &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) !=
|
||||
VK_SUCCESS ||
|
||||
vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) !=
|
||||
vkCreateSemaphore(m_device.device(), &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) !=
|
||||
VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create synchronization objects for a frame!");
|
||||
|
|
@ -414,7 +414,7 @@ namespace hk
|
|||
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
if (vkCreateFence(device.device(), &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS)
|
||||
if (vkCreateFence(m_device.device(), &fenceInfo, nullptr, &m_inFlightFences[i]) != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("failed to create synchronization objects for a frame!");
|
||||
}
|
||||
|
|
@ -469,7 +469,7 @@ namespace hk
|
|||
}
|
||||
else
|
||||
{
|
||||
VkExtent2D actualExtent = windowExtent;
|
||||
VkExtent2D actualExtent = m_windowExtent;
|
||||
actualExtent.width = std::max(
|
||||
capabilities.minImageExtent.width,
|
||||
std::min(capabilities.maxImageExtent.width, actualExtent.width));
|
||||
|
|
@ -483,7 +483,7 @@ namespace hk
|
|||
|
||||
VkFormat SwapChain::findDepthFormat()
|
||||
{
|
||||
return device.findSupportedFormat(
|
||||
return m_device.findSupportedFormat(
|
||||
{VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
||||
|
|
|
|||
|
|
@ -25,18 +25,18 @@ namespace hk
|
|||
SwapChain(const SwapChain &) = delete;
|
||||
SwapChain &operator=(const SwapChain &) = delete;
|
||||
|
||||
VkFramebuffer getFrameBuffer(int index) { return swapChainFramebuffers[index]; }
|
||||
VkRenderPass getRenderPass() { return renderPass; }
|
||||
VkImageView getImageView(int index) { return swapChainImageViews[index]; }
|
||||
size_t imageCount() { return swapChainImages.size(); }
|
||||
VkFormat getSwapChainImageFormat() { return swapChainImageFormat; }
|
||||
VkExtent2D getSwapChainExtent() { return swapChainExtent; }
|
||||
uint32_t width() { return swapChainExtent.width; }
|
||||
uint32_t height() { return swapChainExtent.height; }
|
||||
VkFramebuffer getFrameBuffer(int index) { return m_swapChainFramebuffers[index]; }
|
||||
VkRenderPass getRenderPass() { return m_renderPass; }
|
||||
VkImageView getImageView(int index) { return m_swapChainImageViews[index]; }
|
||||
size_t imageCount() { return m_swapChainImages.size(); }
|
||||
VkFormat getSwapChainImageFormat() { return m_swapChainImageFormat; }
|
||||
VkExtent2D getSwapChainExtent() { return m_swapChainExtent; }
|
||||
uint32_t width() { return m_swapChainExtent.width; }
|
||||
uint32_t height() { return m_swapChainExtent.height; }
|
||||
|
||||
float extentAspectRatio()
|
||||
{
|
||||
return static_cast<float>(swapChainExtent.width) / static_cast<float>(swapChainExtent.height);
|
||||
return static_cast<float>(m_swapChainExtent.width) / static_cast<float>(m_swapChainExtent.height);
|
||||
}
|
||||
VkFormat findDepthFormat();
|
||||
|
||||
|
|
@ -45,8 +45,8 @@ namespace hk
|
|||
|
||||
bool compareSwapFormats(const SwapChain &swapCahin) const
|
||||
{
|
||||
return swapCahin.swapChainDepthFormat == swapChainDepthFormat &&
|
||||
swapCahin.swapChainImageFormat == swapChainImageFormat;
|
||||
return swapCahin.m_swapChainDepthFormat == m_swapChainDepthFormat &&
|
||||
swapCahin.m_swapChainImageFormat == m_swapChainImageFormat;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -65,30 +65,30 @@ namespace hk
|
|||
const std::vector<VkPresentModeKHR> &availablePresentModes);
|
||||
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities);
|
||||
|
||||
VkFormat swapChainImageFormat;
|
||||
VkFormat swapChainDepthFormat;
|
||||
VkExtent2D swapChainExtent;
|
||||
VkFormat m_swapChainImageFormat;
|
||||
VkFormat m_swapChainDepthFormat;
|
||||
VkExtent2D m_swapChainExtent;
|
||||
|
||||
std::vector<VkFramebuffer> swapChainFramebuffers;
|
||||
VkRenderPass renderPass;
|
||||
std::vector<VkFramebuffer> m_swapChainFramebuffers;
|
||||
VkRenderPass m_renderPass;
|
||||
|
||||
std::vector<VkImage> depthImages;
|
||||
std::vector<VkDeviceMemory> depthImageMemorys;
|
||||
std::vector<VkImageView> depthImageViews;
|
||||
std::vector<VkImage> swapChainImages;
|
||||
std::vector<VkImageView> swapChainImageViews;
|
||||
std::vector<VkImage> m_depthImages;
|
||||
std::vector<VkDeviceMemory> m_depthImageMemorys;
|
||||
std::vector<VkImageView> m_depthImageViews;
|
||||
std::vector<VkImage> m_swapChainImages;
|
||||
std::vector<VkImageView> m_swapChainImageViews;
|
||||
|
||||
Device &device;
|
||||
VkExtent2D windowExtent;
|
||||
Device &m_device;
|
||||
VkExtent2D m_windowExtent;
|
||||
|
||||
VkSwapchainKHR swapChain;
|
||||
std::shared_ptr<SwapChain> oldSwapChain;
|
||||
VkSwapchainKHR m_swapChain;
|
||||
std::shared_ptr<SwapChain> m_oldSwapChain;
|
||||
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||
std::vector<VkFence> inFlightFences;
|
||||
std::vector<VkFence> imagesInFlight;
|
||||
size_t currentFrame = 0;
|
||||
std::vector<VkSemaphore> m_imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> m_renderFinishedSemaphores;
|
||||
std::vector<VkFence> m_inFlightFences;
|
||||
std::vector<VkFence> m_imagesInFlight;
|
||||
size_t m_currentFrame = 0;
|
||||
};
|
||||
|
||||
} // namespace hk
|
||||
|
|
|
|||
Loading…
Reference in New Issue