|
|
|
#ifndef HELLOTRIANGLEAPPLICATION_H
|
|
|
|
#define HELLOTRIANGLEAPPLICATION_H
|
|
|
|
|
|
|
|
#ifdef NDEBUG
|
|
|
|
const bool enableValidationLayers = false;
|
|
|
|
#else
|
|
|
|
const bool enableValidationLayers = true;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <vulkan/vulkan.h>
|
|
|
|
|
|
|
|
//#define VK_USE_PLATFORM_
|
|
|
|
//#define GLFW_INCLUDE_VULKAN
|
|
|
|
//#include <GLFW/glfw3.h>
|
|
|
|
//#define GLFW_EXPOSE_NATIVE_
|
|
|
|
//#include <GLFW/glfw3native.h>
|
|
|
|
|
|
|
|
#define GLM_FORCE_RADIANS
|
|
|
|
#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
#include <QObject>
|
|
|
|
#include <QtQuick/QQuickWindow>
|
|
|
|
#include <iostream>
|
|
|
|
#include <optional>
|
|
|
|
#include <cstdint> // Necessary for uint32_t
|
|
|
|
#include <limits> // Necessary for std::numeric_limits
|
|
|
|
#include <algorithm> // Necessary for std::clamp
|
|
|
|
#include <fstream>
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
const QString TARGET_PLATFORM = "Android";
|
|
|
|
#else
|
|
|
|
const QString TARGET_PLATFORM = "Linux";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const int MAX_FRAMES_IN_FLIGHT = 2;
|
|
|
|
|
|
|
|
struct QueueFamilyIndices {
|
|
|
|
std::optional<uint32_t> graphicsFamily;
|
|
|
|
std::optional<uint32_t> presentFamily;
|
|
|
|
|
|
|
|
bool isComplete() {
|
|
|
|
return graphicsFamily.has_value() && presentFamily.has_value();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SwapChainSupportDetails {
|
|
|
|
VkSurfaceCapabilitiesKHR capabilities;
|
|
|
|
std::vector<VkSurfaceFormatKHR> formats;
|
|
|
|
std::vector<VkPresentModeKHR> presentModes;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Vertex {
|
|
|
|
alignas(16) glm::vec2 pos;
|
|
|
|
alignas(16) glm::vec3 color;
|
|
|
|
|
|
|
|
static VkVertexInputBindingDescription getBindingDescription() {
|
|
|
|
VkVertexInputBindingDescription bindingDescription{};
|
|
|
|
bindingDescription.binding = 0;
|
|
|
|
bindingDescription.stride = sizeof(Vertex);
|
|
|
|
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
|
|
|
|
return bindingDescription;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions() {
|
|
|
|
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
|
|
|
|
|
|
|
|
attributeDescriptions[0].binding = 0;
|
|
|
|
attributeDescriptions[0].location = 0;
|
|
|
|
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
|
|
|
|
attributeDescriptions[0].offset = offsetof(Vertex, pos);
|
|
|
|
|
|
|
|
attributeDescriptions[1].binding = 0;
|
|
|
|
attributeDescriptions[1].location = 1;
|
|
|
|
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
|
|
attributeDescriptions[1].offset = offsetof(Vertex, color);
|
|
|
|
|
|
|
|
return attributeDescriptions;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UniformBufferObject {
|
|
|
|
alignas(16) glm::mat4 model;
|
|
|
|
alignas(16) glm::mat4 view;
|
|
|
|
alignas(16) glm::mat4 proj;
|
|
|
|
};
|
|
|
|
|
|
|
|
class HelloTriangleApplication
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
HelloTriangleApplication();
|
|
|
|
void run();
|
|
|
|
|
|
|
|
// Message Callback
|
|
|
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT /*messageSeverity*/,
|
|
|
|
VkDebugUtilsMessageTypeFlagsEXT /*messageType*/,const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,void* /*pUserData*/) {
|
|
|
|
|
|
|
|
std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
|
|
|
|
|
|
|
|
return VK_FALSE;
|
|
|
|
}
|
|
|
|
static std::vector<char> readFile(const std::string& filename);
|
|
|
|
|
|
|
|
// static void framebufferResizeCallback(GLFWwindow* window, int width, int height);
|
|
|
|
static void framebufferResizeCallback(QQuickWindow* window, int width, int height);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void initWindow();
|
|
|
|
void initVulkan();
|
|
|
|
void mainLoop();
|
|
|
|
void cleanup();
|
|
|
|
void createInstance();
|
|
|
|
|
|
|
|
// Enable Validation Layers
|
|
|
|
bool checkValidationLayerSupport();
|
|
|
|
|
|
|
|
// Message Callback
|
|
|
|
std::vector<const char*> getRequiredExtensions();
|
|
|
|
void setupDebugMessenger();
|
|
|
|
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo);
|
|
|
|
|
|
|
|
void pickPhysicalDevice();
|
|
|
|
bool isDeviceSuitable(VkPhysicalDevice device);
|
|
|
|
|
|
|
|
void createLogicalDevice();
|
|
|
|
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
|
|
|
|
|
|
|
|
void createSurface();
|
|
|
|
|
|
|
|
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
|
|
|
|
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
|
|
|
|
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
|
|
|
|
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
|
|
|
|
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
|
|
|
|
void createSwapChain();
|
|
|
|
|
|
|
|
void createImageViews();
|
|
|
|
|
|
|
|
void createGraphicsPipeline();
|
|
|
|
VkShaderModule createShaderModule(const std::vector<char>& code);
|
|
|
|
void createRenderPass();
|
|
|
|
|
|
|
|
void createFramebuffers();
|
|
|
|
void createCommandPool();
|
|
|
|
void createCommandBuffer();
|
|
|
|
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
|
|
|
|
|
|
|
|
void drawFrame();
|
|
|
|
void createSyncObjects();
|
|
|
|
|
|
|
|
void recreateSwapChain();
|
|
|
|
void cleanupSwapChain();
|
|
|
|
|
|
|
|
void createVertexBuffer();
|
|
|
|
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
|
|
|
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory);
|
|
|
|
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
|
|
|
void createIndexBuffer();
|
|
|
|
|
|
|
|
void createDescriptorSetLayout();
|
|
|
|
void createUniformBuffers();
|
|
|
|
void updateUniformBuffer(uint32_t currentImage);
|
|
|
|
void createDescriptorPool();
|
|
|
|
void createDescriptorSets();
|
|
|
|
|
|
|
|
const int32_t WIDTH = 800;
|
|
|
|
const int32_t HEIGHT = 600;
|
|
|
|
const std::vector<const char*> validationLayers = {
|
|
|
|
"VK_LAYER_KHRONOS_validation"
|
|
|
|
};
|
|
|
|
const std::vector<const char*> deviceExtensions = {
|
|
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
|
|
|
};
|
|
|
|
const std::vector<Vertex> vertices = {
|
|
|
|
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
|
|
|
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
|
|
|
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
|
|
|
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}}
|
|
|
|
};
|
|
|
|
const std::vector<uint16_t> indices = {
|
|
|
|
0, 1, 2, 2, 3, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t currentFrame = 0;
|
|
|
|
bool framebufferResized = false;
|
|
|
|
|
|
|
|
// GLFWwindow *_window;
|
|
|
|
QQuickWindow* _window;
|
|
|
|
VkInstance _instance;
|
|
|
|
VkDebugUtilsMessengerEXT _debugMessenger;
|
|
|
|
VkPhysicalDevice _physicalDevice;
|
|
|
|
VkDevice _device;
|
|
|
|
VkQueue _graphicsQueue;
|
|
|
|
VkSurfaceKHR _surface;
|
|
|
|
VkQueue _presentQueue;
|
|
|
|
VkSwapchainKHR _swapChain;
|
|
|
|
std::vector<VkImage> _swapChainImages;
|
|
|
|
VkFormat _swapChainImageFormat;
|
|
|
|
VkExtent2D _swapChainExtent;
|
|
|
|
std::vector<VkImageView> _swapChainImageViews;
|
|
|
|
VkRenderPass _renderPass;
|
|
|
|
VkDescriptorSetLayout _descriptorSetLayout;
|
|
|
|
VkPipelineLayout _pipelineLayout;
|
|
|
|
VkPipeline _graphicsPipeline;
|
|
|
|
std::vector<VkFramebuffer> _swapChainFramebuffers;
|
|
|
|
VkCommandPool _commandPool;
|
|
|
|
std::vector<VkCommandBuffer> _commandBuffers;
|
|
|
|
std::vector<VkSemaphore> _imageAvailableSemaphores;
|
|
|
|
std::vector<VkSemaphore> _renderFinishedSemaphores;
|
|
|
|
std::vector<VkFence> _inFlightFences;
|
|
|
|
VkBuffer _vertexBuffer;
|
|
|
|
VkDeviceMemory _vertexBufferMemory;
|
|
|
|
VkBuffer _indexBuffer;
|
|
|
|
VkDeviceMemory _indexBufferMemory;
|
|
|
|
|
|
|
|
std::vector<VkBuffer> _uniformBuffers;
|
|
|
|
std::vector<VkDeviceMemory> _uniformBuffersMemory;
|
|
|
|
std::vector<void*> _uniformBuffersMapped;
|
|
|
|
VkDescriptorPool _descriptorPool;
|
|
|
|
std::vector<VkDescriptorSet> descriptorSets;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // HELLOTRIANGLEAPPLICATION_H
|