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
std::unique_ptr<Model> createCubeModel(hk::Device &device, glm::vec3 offset)
{
std::vector<Model::Vertex> vertices{
Model::Builder modelBuilder{};
modelBuilder.vertices = {
// left face (white)
{{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}},
{{-.5f, .5f, .5f}, {.9f, .9f, .9f}},
{{-.5f, -.5f, .5f}, {.9f, .9f, .9f}},
{{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}},
{{-.5f, .5f, -.5f}, {.9f, .9f, .9f}},
{{-.5f, .5f, .5f}, {.9f, .9f, .9f}},
// right face (yellow)
{{.5f, -.5f, -.5f}, {.8f, .8f, .1f}},
{{.5f, .5f, .5f}, {.8f, .8f, .1f}},
{{.5f, -.5f, .5f}, {.8f, .8f, .1f}},
{{.5f, -.5f, -.5f}, {.8f, .8f, .1f}},
{{.5f, .5f, -.5f}, {.8f, .8f, .1f}},
{{.5f, .5f, .5f}, {.8f, .8f, .1f}},
// top face (orange, remember y axis points down)
{{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}},
{{.5f, -.5f, .5f}, {.9f, .6f, .1f}},
{{-.5f, -.5f, .5f}, {.9f, .6f, .1f}},
{{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}},
{{.5f, -.5f, -.5f}, {.9f, .6f, .1f}},
{{.5f, -.5f, .5f}, {.9f, .6f, .1f}},
// bottom face (red)
{{-.5f, .5f, -.5f}, {.8f, .1f, .1f}},
{{.5f, .5f, .5f}, {.8f, .1f, .1f}},
{{-.5f, .5f, .5f}, {.8f, .1f, .1f}},
{{-.5f, .5f, -.5f}, {.8f, .1f, .1f}},
{{.5f, .5f, -.5f}, {.8f, .1f, .1f}},
{{.5f, .5f, .5f}, {.8f, .1f, .1f}},
// nose face (blue)
{{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}},
{{.5f, .5f, 0.5f}, {.1f, .1f, .8f}},
{{-.5f, .5f, 0.5f}, {.1f, .1f, .8f}},
{{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}},
{{.5f, -.5f, 0.5f}, {.1f, .1f, .8f}},
{{.5f, .5f, 0.5f}, {.1f, .1f, .8f}},
// tail face (green)
{{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}},
{{.5f, .5f, -0.5f}, {.1f, .8f, .1f}},
{{-.5f, .5f, -0.5f}, {.1f, .8f, .1f}},
{{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}},
{{.5f, -.5f, -0.5f}, {.1f, .8f, .1f}},
{{.5f, .5f, -0.5f}, {.1f, .8f, .1f}},
};
for (auto &v : vertices)
for (auto &v : modelBuilder.vertices)
{
v.position += offset;
}
return std::make_unique<Model>(device, vertices);
modelBuilder.indices = {0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 8, 11, 9,
12, 13, 14, 12, 15, 13, 16, 17, 18, 16, 19, 17, 20, 21, 22, 20, 23, 21};
return std::make_unique<Model>(device, modelBuilder);
}
void FirstApp::loadGameObjects()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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