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
|
// 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()
|
||||||
|
|
|
||||||
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
|
||||||
99
hk_model.cpp
99
hk_model.cpp
|
|
@ -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()
|
||||||
|
|
|
||||||
22
hk_model.hpp
22
hk_model.hpp
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue