16.Index and Staging Buffers

This commit is contained in:
hoenking 2025-12-21 10:57:45 +08:00
parent 6733eb3495
commit 633e6e5105
10 changed files with 292 additions and 222 deletions

Binary file not shown.

View File

@ -70,62 +70,53 @@ namespace hk
// temporary helper function, creates a 1x1x1 cube centered at offset // temporary helper function, creates a 1x1x1 cube centered at offset
std::unique_ptr<Model> createCubeModel(hk::Device &device, glm::vec3 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) // 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}},
{{-.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) // 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}},
{{.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) // 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}},
{{-.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) // 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}},
{{-.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) // 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}},
{{-.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) // 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}},
{{-.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; 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() void FirstApp::loadGameObjects()

View File

@ -55,7 +55,7 @@ namespace hk
} }
// class member functions // class member functions
Device::Device(Window &window) : window{window} Device::Device(Window &window) : m_window{window}
{ {
createInstance(); createInstance();
setupDebugMessenger(); setupDebugMessenger();
@ -67,16 +67,16 @@ namespace hk
Device::~Device() Device::~Device()
{ {
vkDestroyCommandPool(device_, commandPool, nullptr); vkDestroyCommandPool(m_device, m_commandPool, nullptr);
vkDestroyDevice(device_, nullptr); vkDestroyDevice(m_device, nullptr);
if (enableValidationLayers) if (enableValidationLayers)
{ {
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); DestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr);
} }
vkDestroySurfaceKHR(instance, surface_, nullptr); vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
vkDestroyInstance(instance, nullptr); vkDestroyInstance(m_instance, nullptr);
} }
void Device::createInstance() void Device::createInstance()
@ -118,7 +118,7 @@ namespace hk
createInfo.pNext = nullptr; 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!"); throw std::runtime_error("failed to create instance!");
} }
@ -129,36 +129,36 @@ namespace hk
void Device::pickPhysicalDevice() void Device::pickPhysicalDevice()
{ {
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
if (deviceCount == 0) if (deviceCount == 0)
{ {
throw std::runtime_error("failed to find GPUs with Vulkan support!"); throw std::runtime_error("failed to find GPUs with Vulkan support!");
} }
std::cout << "Device count: " << deviceCount << std::endl; std::cout << "Device count: " << deviceCount << std::endl;
std::vector<VkPhysicalDevice> devices(deviceCount); std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
for (const auto &device : devices) for (const auto &device : devices)
{ {
if (isDeviceSuitable(device)) if (isDeviceSuitable(device))
{ {
physicalDevice = device; m_physicalDevice = device;
break; break;
} }
} }
if (physicalDevice == VK_NULL_HANDLE) if (m_physicalDevice == VK_NULL_HANDLE)
{ {
throw std::runtime_error("failed to find a suitable GPU!"); 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; std::cout << "physical device: " << properties.deviceName << std::endl;
} }
void Device::createLogicalDevice() void Device::createLogicalDevice()
{ {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice); QueueFamilyIndices indices = findQueueFamilies(m_physicalDevice);
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily}; std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily};
@ -184,16 +184,16 @@ namespace hk
createInfo.pQueueCreateInfos = queueCreateInfos.data(); createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.pEnabledFeatures = &deviceFeatures; createInfo.pEnabledFeatures = &deviceFeatures;
// Add device extensions, including portability subset if available (needed for MoltenVK) // 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 // Check if VK_KHR_portability_subset is available and add it if needed
uint32_t extensionCount; uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr); vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount); std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data()); vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extensionCount, availableExtensions.data());
for (const auto &extension : availableExtensions) for (const auto &extension : availableExtensions)
{ {
if (strcmp(extension.extensionName, "VK_KHR_portability_subset") == 0) if (strcmp(extension.extensionName, "VK_KHR_portability_subset") == 0)
@ -202,7 +202,7 @@ namespace hk
break; break;
} }
} }
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
createInfo.ppEnabledExtensionNames = enabledExtensions.data(); createInfo.ppEnabledExtensionNames = enabledExtensions.data();
@ -218,13 +218,13 @@ namespace hk
createInfo.enabledLayerCount = 0; 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!"); throw std::runtime_error("failed to create logical device!");
} }
vkGetDeviceQueue(device_, indices.graphicsFamily, 0, &graphicsQueue_); vkGetDeviceQueue(m_device, indices.graphicsFamily, 0, &m_graphicsQueue);
vkGetDeviceQueue(device_, indices.presentFamily, 0, &presentQueue_); vkGetDeviceQueue(m_device, indices.presentFamily, 0, &m_presentQueue);
} }
void Device::createCommandPool() void Device::createCommandPool()
@ -237,13 +237,13 @@ namespace hk
poolInfo.flags = poolInfo.flags =
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 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!"); 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) bool Device::isDeviceSuitable(VkPhysicalDevice device)
{ {
@ -285,7 +285,7 @@ namespace hk
return; return;
VkDebugUtilsMessengerCreateInfoEXT createInfo; VkDebugUtilsMessengerCreateInfoEXT createInfo;
populateDebugMessengerCreateInfo(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!"); throw std::runtime_error("failed to set up debug messenger!");
} }
@ -408,7 +408,7 @@ namespace hk
indices.graphicsFamilyHasValue = true; indices.graphicsFamilyHasValue = true;
} }
VkBool32 presentSupport = false; VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface_, &presentSupport); vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport);
if (queueFamily.queueCount > 0 && presentSupport) if (queueFamily.queueCount > 0 && presentSupport)
{ {
indices.presentFamily = i; indices.presentFamily = i;
@ -428,26 +428,26 @@ namespace hk
SwapChainSupportDetails Device::querySwapChainSupport(VkPhysicalDevice device) SwapChainSupportDetails Device::querySwapChainSupport(VkPhysicalDevice device)
{ {
SwapChainSupportDetails details; SwapChainSupportDetails details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.capabilities); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities);
uint32_t formatCount; uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, nullptr); vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr);
if (formatCount != 0) if (formatCount != 0)
{ {
details.formats.resize(formatCount); details.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, details.formats.data()); vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data());
} }
uint32_t presentModeCount; uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, nullptr); vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr);
if (presentModeCount != 0) if (presentModeCount != 0)
{ {
details.presentModes.resize(presentModeCount); details.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR( vkGetPhysicalDeviceSurfacePresentModesKHR(
device, device,
surface_, m_surface,
&presentModeCount, &presentModeCount,
details.presentModes.data()); details.presentModes.data());
} }
@ -460,7 +460,7 @@ namespace hk
for (VkFormat format : candidates) for (VkFormat format : candidates)
{ {
VkFormatProperties props; VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props); vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &props);
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) 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) uint32_t Device::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
{ {
VkPhysicalDeviceMemoryProperties memProperties; VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memProperties);
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
{ {
if ((typeFilter & (1 << i)) && if ((typeFilter & (1 << i)) &&
@ -504,25 +504,25 @@ namespace hk
bufferInfo.usage = usage; bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 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!"); throw std::runtime_error("failed to create vertex buffer!");
} }
VkMemoryRequirements memRequirements; VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device_, buffer, &memRequirements); vkGetBufferMemoryRequirements(m_device, buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{}; VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size; allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); 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!"); throw std::runtime_error("failed to allocate vertex buffer memory!");
} }
vkBindBufferMemory(device_, buffer, bufferMemory, 0); vkBindBufferMemory(m_device, buffer, bufferMemory, 0);
} }
VkCommandBuffer Device::beginSingleTimeCommands() VkCommandBuffer Device::beginSingleTimeCommands()
@ -530,11 +530,11 @@ namespace hk
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = commandPool; allocInfo.commandPool = m_commandPool;
allocInfo.commandBufferCount = 1; allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer; VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(device_, &allocInfo, &commandBuffer); vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -553,10 +553,10 @@ namespace hk
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(graphicsQueue_, 1, &submitInfo, VK_NULL_HANDLE); vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(graphicsQueue_); vkQueueWaitIdle(m_graphicsQueue);
vkFreeCommandBuffers(device_, commandPool, 1, &commandBuffer); vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
} }
void Device::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) void Device::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
@ -606,25 +606,25 @@ namespace hk
VkImage &image, VkImage &image,
VkDeviceMemory &imageMemory) 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!"); throw std::runtime_error("failed to create image!");
} }
VkMemoryRequirements memRequirements; VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(device_, image, &memRequirements); vkGetImageMemoryRequirements(m_device, image, &memRequirements);
VkMemoryAllocateInfo allocInfo{}; VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size; allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); 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!"); 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!"); throw std::runtime_error("failed to bind image memory!");
} }

View File

@ -43,15 +43,15 @@ namespace hk
Device(Device &&) = delete; Device(Device &&) = delete;
Device &operator=(Device &&) = delete; Device &operator=(Device &&) = delete;
VkCommandPool getCommandPool() { return commandPool; } VkCommandPool getCommandPool() { return m_commandPool; }
VkDevice device() { return device_; } VkDevice device() { return m_device; }
VkSurfaceKHR surface() { return surface_; } VkSurfaceKHR surface() { return m_surface; }
VkQueue graphicsQueue() { return graphicsQueue_; } VkQueue graphicsQueue() { return m_graphicsQueue; }
VkQueue presentQueue() { return presentQueue_; } VkQueue presentQueue() { return m_presentQueue; }
SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(physicalDevice); } SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(m_physicalDevice); }
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
QueueFamilyIndices findPhysicalQueueFamilies() { return findQueueFamilies(physicalDevice); } QueueFamilyIndices findPhysicalQueueFamilies() { return findQueueFamilies(m_physicalDevice); }
VkFormat findSupportedFormat( VkFormat findSupportedFormat(
const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
@ -94,16 +94,16 @@ namespace hk
bool checkDeviceExtensionSupport(VkPhysicalDevice device); bool checkDeviceExtensionSupport(VkPhysicalDevice device);
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
VkInstance instance; VkInstance m_instance;
VkDebugUtilsMessengerEXT debugMessenger; VkDebugUtilsMessengerEXT m_debugMessenger;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
Window &window; Window &m_window;
VkCommandPool commandPool; VkCommandPool m_commandPool;
VkDevice device_; VkDevice m_device;
VkSurfaceKHR surface_; VkSurfaceKHR m_surface;
VkQueue graphicsQueue_; VkQueue m_graphicsQueue;
VkQueue presentQueue_; VkQueue m_presentQueue;
const std::vector<const char *> validationLayers = {"VK_LAYER_KHRONOS_validation"}; const std::vector<const char *> validationLayers = {"VK_LAYER_KHRONOS_validation"};
const std::vector<const char *> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; const std::vector<const char *> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};

View File

@ -4,45 +4,112 @@
#include <cstring> #include <cstring>
namespace hk{ namespace hk{
Model::Model(Device &device, const std::vector<Vertex> &vertices) Model::Model(Device &device, const Builder &builder)
: device{device} : m_device{device}
{ {
createVertexBuffers(vertices); createVertexBuffers(builder.vertices);
createIndexBuffers(builder.indices);
} }
Model::~Model() Model::~Model()
{ {
vkDestroyBuffer(device.device(), vertexBuffer, nullptr); vkDestroyBuffer(m_device.device(), m_vertexBuffer, nullptr);
vkFreeMemory(device.device(), vertexBufferMemory, 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) void Model::createVertexBuffers(const std::vector<Vertex> &vertices)
{ {
vertexCount = static_cast<uint32_t>(vertices.size()); m_vertexCount = static_cast<uint32_t>(vertices.size());
assert(vertexCount >= 3 && "Vertex count must be at least 3"); assert(m_vertexCount >= 3 && "Vertex count must be at least 3");
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount; VkDeviceSize bufferSize = sizeof(vertices[0]) * m_vertexCount;
device.createBuffer(
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
m_device.createBuffer(
bufferSize, 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, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
vertexBuffer, stagingBuffer,
vertexBufferMemory stagingBufferMemory
); );
void *data; 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)); 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) void Model::bind(VkCommandBuffer commandBuffer)
{ {
VkBuffer buffers[] = {vertexBuffer}; VkBuffer buffers[] = {m_vertexBuffer};
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
if (m_hasIndexBuffer)
{
vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT32);
}
} }
void Model::draw(VkCommandBuffer commandBuffer) 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() std::vector<VkVertexInputBindingDescription> Model::Vertex::getBindingDescriptions()

View File

@ -20,7 +20,13 @@ namespace hk{
static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions(); 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();
Model(const Model &) = delete; Model(const Model &) = delete;
@ -30,10 +36,16 @@ namespace hk{
void draw(VkCommandBuffer commandBuffer); void draw(VkCommandBuffer commandBuffer);
private: private:
void createVertexBuffers(const std::vector<Vertex> &vertices); void createVertexBuffers(const std::vector<Vertex> &vertices);
void createIndexBuffers(const std::vector<uint32_t> &indices);
Device &device; Device &m_device;
VkBuffer vertexBuffer; VkBuffer m_vertexBuffer;
VkDeviceMemory vertexBufferMemory; VkDeviceMemory m_vertexBufferMemory;
uint32_t vertexCount; uint32_t m_vertexCount;
bool m_hasIndexBuffer = false;
VkBuffer m_indexBuffer;
VkDeviceMemory m_indexBufferMemory;
uint32_t m_indexCount;
}; };
} }

View File

@ -14,21 +14,21 @@ namespace hk
Device& device, Device& device,
const std::string &vertFilePath, const std::string &vertFilePath,
const std::string &fragFilePath, const std::string &fragFilePath,
const PipelineConfigInfo& configInfo) : device(device) const PipelineConfigInfo& configInfo) : m_device(device)
{ {
createGraphicPipeline(vertFilePath, fragFilePath, configInfo); createGraphicPipeline(vertFilePath, fragFilePath, configInfo);
} }
Pipeline::~Pipeline() Pipeline::~Pipeline()
{ {
vkDestroyShaderModule(device.device(), vertShaderModule, nullptr); vkDestroyShaderModule(m_device.device(), m_vertShaderModule, nullptr);
vkDestroyShaderModule(device.device(), fragShaderModule, nullptr); vkDestroyShaderModule(m_device.device(), m_fragShaderModule, nullptr);
vkDestroyPipeline(device.device(), graphicPipeline, nullptr); vkDestroyPipeline(m_device.device(), m_graphicPipeline, nullptr);
} }
void Pipeline::bind(VkCommandBuffer commandBuffer) 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) void Pipeline::defaultPipelineConfigInfo(PipelineConfigInfo& configInfo)
@ -134,13 +134,13 @@ namespace hk
std::vector<char> vertCode = readFile(vertFilePath); std::vector<char> vertCode = readFile(vertFilePath);
std::vector<char> fragCode = readFile(fragFilePath); std::vector<char> fragCode = readFile(fragFilePath);
createShaderModule(vertCode, &vertShaderModule); createShaderModule(vertCode, &m_vertShaderModule);
createShaderModule(fragCode, &fragShaderModule); createShaderModule(fragCode, &m_fragShaderModule);
VkPipelineShaderStageCreateInfo shaderStages[2]; VkPipelineShaderStageCreateInfo shaderStages[2];
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = vertShaderModule; shaderStages[0].module = m_vertShaderModule;
shaderStages[0].pName = "main"; shaderStages[0].pName = "main";
shaderStages[0].flags = 0; shaderStages[0].flags = 0;
shaderStages[0].pNext = nullptr; shaderStages[0].pNext = nullptr;
@ -148,7 +148,7 @@ namespace hk
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = fragShaderModule; shaderStages[1].module = m_fragShaderModule;
shaderStages[1].pName = "main"; shaderStages[1].pName = "main";
shaderStages[1].flags = 0; shaderStages[1].flags = 0;
shaderStages[1].pNext = nullptr; shaderStages[1].pNext = nullptr;
@ -184,7 +184,7 @@ namespace hk
pipelineInfo.basePipelineIndex = -1; pipelineInfo.basePipelineIndex = -1;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; 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!"); throw std::runtime_error("failed to create graphics pipeline!");
} }
@ -197,7 +197,7 @@ namespace hk
createInfo.codeSize = code.size(); createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data()); 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!"); throw std::runtime_error("failed to create shader module!");
} }

View File

@ -53,9 +53,9 @@ namespace hk
void createShaderModule(const std::vector<char>& code, VkShaderModule* shaderModule); void createShaderModule(const std::vector<char>& code, VkShaderModule* shaderModule);
Device& device; Device& m_device;
VkPipeline graphicPipeline; VkPipeline m_graphicPipeline;
VkShaderModule vertShaderModule; VkShaderModule m_vertShaderModule;
VkShaderModule fragShaderModule; VkShaderModule m_fragShaderModule;
}; };
} }

View File

@ -13,19 +13,19 @@ namespace hk
{ {
SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent) SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent)
: device{deviceRef}, windowExtent{extent} : m_device{deviceRef}, m_windowExtent{extent}
{ {
init(); init();
} }
SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent, std::shared_ptr<SwapChain> previous) 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(); init();
// Reset currentFrame to 0 when creating a new swap chain // Reset currentFrame to 0 when creating a new swap chain
currentFrame = 0; m_currentFrame = 0;
// clean up old swap chain // clean up old swap chain
oldSwapChain = nullptr; m_oldSwapChain = nullptr;
} }
void SwapChain::init() void SwapChain::init()
@ -40,59 +40,59 @@ namespace hk
SwapChain::~SwapChain() 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); vkDestroySwapchainKHR(m_device.device(), m_swapChain, nullptr);
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); vkDestroyImageView(m_device.device(), m_depthImageViews[i], nullptr);
vkDestroyImage(device.device(), depthImages[i], nullptr); vkDestroyImage(m_device.device(), m_depthImages[i], nullptr);
vkFreeMemory(device.device(), depthImageMemorys[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 // 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(m_device.device(), m_renderFinishedSemaphores[i], nullptr);
vkDestroySemaphore(device.device(), imageAvailableSemaphores[i], nullptr); vkDestroySemaphore(m_device.device(), m_imageAvailableSemaphores[i], nullptr);
} }
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) 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) VkResult SwapChain::acquireNextImage(uint32_t *imageIndex)
{ {
vkWaitForFences( vkWaitForFences(
device.device(), m_device.device(),
1, 1,
&inFlightFences[currentFrame], &m_inFlightFences[m_currentFrame],
VK_TRUE, VK_TRUE,
std::numeric_limits<uint64_t>::max()); std::numeric_limits<uint64_t>::max());
// Acquire with a temporary semaphore, we'll use the imageIndex-specific one later // Acquire with a temporary semaphore, we'll use the imageIndex-specific one later
VkResult result = vkAcquireNextImageKHR( VkResult result = vkAcquireNextImageKHR(
device.device(), m_device.device(),
swapChain, m_swapChain,
std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(),
imageAvailableSemaphores[currentFrame % imageAvailableSemaphores.size()], m_imageAvailableSemaphores[m_currentFrame % m_imageAvailableSemaphores.size()],
VK_NULL_HANDLE, VK_NULL_HANDLE,
imageIndex); imageIndex);
@ -102,17 +102,17 @@ namespace hk
VkResult SwapChain::submitCommandBuffers( VkResult SwapChain::submitCommandBuffers(
const VkCommandBuffer *buffers, uint32_t *imageIndex) 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 = {}; VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
// Use the semaphore associated with the currentFrame for waiting (from acquireNextImage) // 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}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
@ -122,12 +122,12 @@ namespace hk
submitInfo.pCommandBuffers = buffers; submitInfo.pCommandBuffers = buffers;
// Use the semaphore associated with this specific image for signaling // Use the semaphore associated with this specific image for signaling
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[*imageIndex]}; VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[*imageIndex]};
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device.device(), 1, &inFlightFences[currentFrame]); vkResetFences(m_device.device(), 1, &m_inFlightFences[m_currentFrame]);
if (vkQueueSubmit(device.graphicsQueue(), 1, &submitInfo, inFlightFences[currentFrame]) != if (vkQueueSubmit(m_device.graphicsQueue(), 1, &submitInfo, m_inFlightFences[m_currentFrame]) !=
VK_SUCCESS) VK_SUCCESS)
{ {
throw std::runtime_error("failed to submit draw command buffer!"); throw std::runtime_error("failed to submit draw command buffer!");
@ -139,22 +139,22 @@ namespace hk
presentInfo.waitSemaphoreCount = 1; presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores; presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = {swapChain}; VkSwapchainKHR swapChains[] = {m_swapChain};
presentInfo.swapchainCount = 1; presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains; presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = imageIndex; 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; return result;
} }
void SwapChain::createSwapChain() void SwapChain::createSwapChain()
{ {
SwapChainSupportDetails swapChainSupport = device.getSwapChainSupport(); SwapChainSupportDetails swapChainSupport = m_device.getSwapChainSupport();
VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
@ -169,7 +169,7 @@ namespace hk
VkSwapchainCreateInfoKHR createInfo = {}; VkSwapchainCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = device.surface(); createInfo.surface = m_device.surface();
createInfo.minImageCount = imageCount; createInfo.minImageCount = imageCount;
createInfo.imageFormat = surfaceFormat.format; createInfo.imageFormat = surfaceFormat.format;
@ -178,7 +178,7 @@ namespace hk
createInfo.imageArrayLayers = 1; createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
QueueFamilyIndices indices = device.findPhysicalQueueFamilies(); QueueFamilyIndices indices = m_device.findPhysicalQueueFamilies();
uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily}; uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily};
if (indices.graphicsFamily != indices.presentFamily) if (indices.graphicsFamily != indices.presentFamily)
@ -200,9 +200,9 @@ namespace hk
createInfo.presentMode = presentMode; createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE; 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!"); 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 // 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 // images with vkGetSwapchainImagesKHR, then resize the container and finally call it again to
// retrieve the handles. // retrieve the handles.
vkGetSwapchainImagesKHR(device.device(), swapChain, &imageCount, nullptr); vkGetSwapchainImagesKHR(m_device.device(), m_swapChain, &imageCount, nullptr);
swapChainImages.resize(imageCount); m_swapChainImages.resize(imageCount);
vkGetSwapchainImagesKHR(device.device(), swapChain, &imageCount, swapChainImages.data()); vkGetSwapchainImagesKHR(m_device.device(), m_swapChain, &imageCount, m_swapChainImages.data());
swapChainImageFormat = surfaceFormat.format; m_swapChainImageFormat = surfaceFormat.format;
swapChainExtent = extent; m_swapChainExtent = extent;
} }
void SwapChain::createImageViews() void SwapChain::createImageViews()
{ {
swapChainImageViews.resize(swapChainImages.size()); m_swapChainImageViews.resize(m_swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++) for (size_t i = 0; i < m_swapChainImages.size(); i++)
{ {
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 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.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = swapChainImageFormat; viewInfo.format = m_swapChainImageFormat;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(device.device(), &viewInfo, nullptr, &swapChainImageViews[i]) != if (vkCreateImageView(m_device.device(), &viewInfo, nullptr, &m_swapChainImageViews[i]) !=
VK_SUCCESS) VK_SUCCESS)
{ {
throw std::runtime_error("failed to create texture image view!"); throw std::runtime_error("failed to create texture image view!");
@ -300,7 +300,7 @@ namespace hk
renderPassInfo.dependencyCount = 1; renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency; 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!"); throw std::runtime_error("failed to create render pass!");
} }
@ -308,15 +308,15 @@ namespace hk
void SwapChain::createFramebuffers() void SwapChain::createFramebuffers()
{ {
swapChainFramebuffers.resize(imageCount()); m_swapChainFramebuffers.resize(imageCount());
for (size_t i = 0; i < imageCount(); i++) 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(); VkExtent2D swapChainExtent = getSwapChainExtent();
VkFramebufferCreateInfo framebufferInfo = {}; VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = renderPass; framebufferInfo.renderPass = m_renderPass;
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size()); framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferInfo.pAttachments = attachments.data(); framebufferInfo.pAttachments = attachments.data();
framebufferInfo.width = swapChainExtent.width; framebufferInfo.width = swapChainExtent.width;
@ -324,10 +324,10 @@ namespace hk
framebufferInfo.layers = 1; framebufferInfo.layers = 1;
if (vkCreateFramebuffer( if (vkCreateFramebuffer(
device.device(), m_device.device(),
&framebufferInfo, &framebufferInfo,
nullptr, nullptr,
&swapChainFramebuffers[i]) != VK_SUCCESS) &m_swapChainFramebuffers[i]) != VK_SUCCESS)
{ {
throw std::runtime_error("failed to create framebuffer!"); throw std::runtime_error("failed to create framebuffer!");
} }
@ -337,14 +337,14 @@ namespace hk
void SwapChain::createDepthResources() void SwapChain::createDepthResources()
{ {
VkFormat depthFormat = findDepthFormat(); VkFormat depthFormat = findDepthFormat();
swapChainDepthFormat = depthFormat; m_swapChainDepthFormat = depthFormat;
VkExtent2D swapChainExtent = getSwapChainExtent(); VkExtent2D swapChainExtent = getSwapChainExtent();
depthImages.resize(imageCount()); m_depthImages.resize(imageCount());
depthImageMemorys.resize(imageCount()); m_depthImageMemorys.resize(imageCount());
depthImageViews.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{}; VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -362,15 +362,15 @@ namespace hk
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.flags = 0; imageInfo.flags = 0;
device.createImageWithInfo( m_device.createImageWithInfo(
imageInfo, imageInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
depthImages[i], m_depthImages[i],
depthImageMemorys[i]); m_depthImageMemorys[i]);
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 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.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = depthFormat; viewInfo.format = depthFormat;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
@ -379,7 +379,7 @@ namespace hk
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1; 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!"); throw std::runtime_error("failed to create texture image view!");
} }
@ -389,10 +389,10 @@ namespace hk
void SwapChain::createSyncObjects() void SwapChain::createSyncObjects()
{ {
// Create one set of semaphores for each swapchain image // Create one set of semaphores for each swapchain image
imageAvailableSemaphores.resize(imageCount()); m_imageAvailableSemaphores.resize(imageCount());
renderFinishedSemaphores.resize(imageCount()); m_renderFinishedSemaphores.resize(imageCount());
inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
imagesInFlight.resize(imageCount(), VK_NULL_HANDLE); m_imagesInFlight.resize(imageCount(), VK_NULL_HANDLE);
VkSemaphoreCreateInfo semaphoreInfo = {}; VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@ -403,9 +403,9 @@ namespace hk
for (size_t i = 0; i < imageCount(); i++) 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 || VK_SUCCESS ||
vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != vkCreateSemaphore(m_device.device(), &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) !=
VK_SUCCESS) VK_SUCCESS)
{ {
throw std::runtime_error("failed to create synchronization objects for a frame!"); 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++) 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!"); throw std::runtime_error("failed to create synchronization objects for a frame!");
} }
@ -469,7 +469,7 @@ namespace hk
} }
else else
{ {
VkExtent2D actualExtent = windowExtent; VkExtent2D actualExtent = m_windowExtent;
actualExtent.width = std::max( actualExtent.width = std::max(
capabilities.minImageExtent.width, capabilities.minImageExtent.width,
std::min(capabilities.maxImageExtent.width, actualExtent.width)); std::min(capabilities.maxImageExtent.width, actualExtent.width));
@ -483,7 +483,7 @@ namespace hk
VkFormat SwapChain::findDepthFormat() 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_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT},
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);

View File

@ -25,18 +25,18 @@ namespace hk
SwapChain(const SwapChain &) = delete; SwapChain(const SwapChain &) = delete;
SwapChain &operator=(const SwapChain &) = delete; SwapChain &operator=(const SwapChain &) = delete;
VkFramebuffer getFrameBuffer(int index) { return swapChainFramebuffers[index]; } VkFramebuffer getFrameBuffer(int index) { return m_swapChainFramebuffers[index]; }
VkRenderPass getRenderPass() { return renderPass; } VkRenderPass getRenderPass() { return m_renderPass; }
VkImageView getImageView(int index) { return swapChainImageViews[index]; } VkImageView getImageView(int index) { return m_swapChainImageViews[index]; }
size_t imageCount() { return swapChainImages.size(); } size_t imageCount() { return m_swapChainImages.size(); }
VkFormat getSwapChainImageFormat() { return swapChainImageFormat; } VkFormat getSwapChainImageFormat() { return m_swapChainImageFormat; }
VkExtent2D getSwapChainExtent() { return swapChainExtent; } VkExtent2D getSwapChainExtent() { return m_swapChainExtent; }
uint32_t width() { return swapChainExtent.width; } uint32_t width() { return m_swapChainExtent.width; }
uint32_t height() { return swapChainExtent.height; } uint32_t height() { return m_swapChainExtent.height; }
float extentAspectRatio() 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(); VkFormat findDepthFormat();
@ -45,8 +45,8 @@ namespace hk
bool compareSwapFormats(const SwapChain &swapCahin) const bool compareSwapFormats(const SwapChain &swapCahin) const
{ {
return swapCahin.swapChainDepthFormat == swapChainDepthFormat && return swapCahin.m_swapChainDepthFormat == m_swapChainDepthFormat &&
swapCahin.swapChainImageFormat == swapChainImageFormat; swapCahin.m_swapChainImageFormat == m_swapChainImageFormat;
} }
private: private:
@ -65,30 +65,30 @@ namespace hk
const std::vector<VkPresentModeKHR> &availablePresentModes); const std::vector<VkPresentModeKHR> &availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities);
VkFormat swapChainImageFormat; VkFormat m_swapChainImageFormat;
VkFormat swapChainDepthFormat; VkFormat m_swapChainDepthFormat;
VkExtent2D swapChainExtent; VkExtent2D m_swapChainExtent;
std::vector<VkFramebuffer> swapChainFramebuffers; std::vector<VkFramebuffer> m_swapChainFramebuffers;
VkRenderPass renderPass; VkRenderPass m_renderPass;
std::vector<VkImage> depthImages; std::vector<VkImage> m_depthImages;
std::vector<VkDeviceMemory> depthImageMemorys; std::vector<VkDeviceMemory> m_depthImageMemorys;
std::vector<VkImageView> depthImageViews; std::vector<VkImageView> m_depthImageViews;
std::vector<VkImage> swapChainImages; std::vector<VkImage> m_swapChainImages;
std::vector<VkImageView> swapChainImageViews; std::vector<VkImageView> m_swapChainImageViews;
Device &device; Device &m_device;
VkExtent2D windowExtent; VkExtent2D m_windowExtent;
VkSwapchainKHR swapChain; VkSwapchainKHR m_swapChain;
std::shared_ptr<SwapChain> oldSwapChain; std::shared_ptr<SwapChain> m_oldSwapChain;
std::vector<VkSemaphore> imageAvailableSemaphores; std::vector<VkSemaphore> m_imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores; std::vector<VkSemaphore> m_renderFinishedSemaphores;
std::vector<VkFence> inFlightFences; std::vector<VkFence> m_inFlightFences;
std::vector<VkFence> imagesInFlight; std::vector<VkFence> m_imagesInFlight;
size_t currentFrame = 0; size_t m_currentFrame = 0;
}; };
} // namespace hk } // namespace hk