Test Vulkan code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

395 lines
17 KiB

#ifndef COMPUTEANDGRAPHICS_H
#define COMPUTEANDGRAPHICS_H
#pragma once
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
#include "Types.h"
#include "VulkanWindow.h"
#include <chrono>
#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>
#include <QFile>
#include <QDomDocument>
#include <QString>
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 ComputeParameters {
alignas(16) glm::uint32 tintMapType;
};
struct Vertex {
alignas(16) glm::vec3 pos;
alignas(16) glm::vec3 color;
alignas(16) glm::vec2 texCoord;
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, 3> getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_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);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
return attributeDescriptions;
}
bool operator==(const Vertex& other) const {
return pos == other.pos && color == other.color && texCoord == other.texCoord;
}
};
struct UniformBufferObject {
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
class ComputeAndGraphics
{
public:
ComputeAndGraphics();
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 pickPhysicalDevice();
void chooseDevice(uint32_t deviceCount);
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();
void createTextureImage();
void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage
, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory);
VkCommandBuffer beginSingleTimeCommands();
void endSingleTimeCommands(VkCommandBuffer commandBuffer);
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels);
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height);
void createTextureImageView();
VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels);
void createTextureSampler();
void createDepthResources();
VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
VkFormat findDepthFormat();
bool hasStencilComponent(VkFormat format);
void createShaderStorageBuffers();
void createComputePipeline();
void createComputeCommandBuffers();
void recordComputeCommandBuffer(VkCommandBuffer commandBuffer);
void createComputeDescriptorSets();
void createComputeDescriptorSetLayout();
void createComputeDescriptorPool();
void createComputeStorageBuffers();
void initComputeStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize);
void createComputeUniformBuffers();
void updateComputeUniformBuffer(uint32_t currentImage);
VkApplicationInfo createInstanceAppInfo();
VkDebugUtilsMessengerCreateInfoEXT createInstanceDebugMessengerInfo();
VkInstanceCreateInfo createInstanceInfo(VkApplicationInfo* appInfo, std::vector<const char*>& extensions
, VkDebugUtilsMessengerCreateInfoEXT& debugCreateInfo);
VkDeviceQueueCreateInfo createQueueInfo(uint32_t queueFamily, uint32_t queueCount, float* queuePriority);
VkPhysicalDeviceFeatures createDeviceCoreFeatures();
VkPhysicalDeviceVulkan12Features createDeviceVulkan12Features(void* pNext);
VkPhysicalDeviceVulkan13Features createDeviceVulkan13Features(void* pNext);
VkPhysicalDeviceFeatures2KHR createDeviceCoreFeatures2(VkPhysicalDevice8BitStorageFeaturesKHR* pNext);
VkPhysicalDevice8BitStorageFeaturesKHR createDevice8BitStorageFeatures2Info();
VkDeviceCreateInfo createLogicalDeviceInfo(std::vector<VkDeviceQueueCreateInfo>& queueCreateInfos, VkPhysicalDeviceFeatures* deviceFeatures
, void* pNext);
VkSwapchainCreateInfoKHR createSwapChainInfo(SwapChainSupportDetails swapChainSupport, VkSurfaceKHR _surface, uint32_t imageCount
, VkSurfaceFormatKHR surfaceFormat, VkExtent2D extent, VkPresentModeKHR presentMode);
VkAttachmentDescription createColorAttachmentInfo(VkFormat format, VkSampleCountFlagBits msaaSamples);
VkAttachmentDescription createDepthAttachmentInfo(VkFormat format, VkSampleCountFlagBits msaaSamples);
VkAttachmentReference createAttachmentRefInfo(uint32_t offset, VkImageLayout layout);
VkSubpassDescription createSubpassInfo(VkAttachmentReference* colorAttachRef, VkAttachmentReference* depthAttachRef);
VkRenderPassCreateInfo createRenderPassInfo(std::vector<VkAttachmentDescription>& attachments, VkSubpassDescription* subpass, VkSubpassDependency* dependency);
VkSubpassDependency createSubpassDependencyInfo();
VkDescriptorSetLayoutBinding createLayoutBindingInfo(uint32_t offset, VkDescriptorType descType, VkShaderStageFlagBits StageFlags);
VkPipelineShaderStageCreateInfo createPipelineShaderInfo(VkShaderStageFlagBits stage, VkShaderModule module);
VkPipelineVertexInputStateCreateInfo createPipelineVertexInputInfo();
VkPipelineInputAssemblyStateCreateInfo createPipelineInputAssemblyStateInfo();
VkPipelineDynamicStateCreateInfo createPipelineDynamicStateInfo(std::vector<VkDynamicState>& dynamicStates);
VkPipelineViewportStateCreateInfo createPipelineViewportStateInfo();
VkPipelineRasterizationStateCreateInfo createPipelineRasterizationStateInfo();
VkPipelineMultisampleStateCreateInfo createPipelineMultisampleStateInfo();
VkPipelineColorBlendAttachmentState colorPipelineBlendAttachmentStateInfo();
VkPipelineColorBlendStateCreateInfo colorPipelineBlendStateInfo(VkPipelineColorBlendAttachmentState* colorBlendAttachment);
VkPipelineLayoutCreateInfo createPipelineLayoutInfo();
VkPipelineDepthStencilStateCreateInfo createPipelineDepthStencilStateInfo();
VkPipelineLayoutCreateInfo createComputePipelineLayoutInfo();
VkFramebufferCreateInfo createFramebufferInfo(std::vector<VkImageView>& attachments);
void copyImageToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory, stbi_uc* pixels, VkDeviceSize imageSize);
VkImageMemoryBarrier initTransitionLayoutBarrierInfo(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels);
void setSrcAndDst(VkImageMemoryBarrier& barrier, VkPipelineStageFlags& sourceStage, VkPipelineStageFlags& destinationStage, VkImageLayout oldLayout
, VkImageLayout newLayout);
void allocateAndBindImageMemory(VkImage& image, VkDeviceMemory& imageMemory, VkMemoryPropertyFlags properties);
VkBufferImageCopy createBufferImageCopyInfo(uint32_t width, uint32_t height);
void copyVerticesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory);
void copyIndicesToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory);
void allocateAndBindBufferMemory(VkBuffer& buffer, VkDeviceMemory& bufferMemory, VkMemoryPropertyFlags properties);
void initShaderStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize);
void allocateDescriptorSets();
VkDescriptorBufferInfo createDescriptorBufferInfo(VkBuffer buffer, VkDeviceSize range);
VkDescriptorImageInfo createDescriptorImageInfo();
void addUniformBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void addImageWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorImageInfo* imageInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void allocateComputeDescriptorSets();
void addStorageBufferWriteDescriptor(VkWriteDescriptorSet& descriptorWrite, VkDescriptorBufferInfo* bufferInfo, VkDescriptorSet dstSet, uint32_t dstBinding);
void computeSubmission();
VkSubmitInfo createComputeSubmitInfo();
VkResult graphicsSubmission();
void drawSubmission(uint32_t imageIndex, VkSemaphore* waitSemaphores, VkPipelineStageFlags* waitStages, VkSemaphore* signalSemaphores);
VkSubmitInfo createDrawSubmitInfo(VkSemaphore* waitSemaphores, VkPipelineStageFlags* waitStages, VkSemaphore* signalSemaphores);
VkResult presentSubmission(uint32_t imageIndex, VkSemaphore* signalSemaphores);
VkViewport createViewportInfo();
VkRect2D createScissorInfo();
void beginPipelineCommands(VkCommandBuffer commandBuffer);
void beginRenderPass(VkCommandBuffer commandBuffer, uint32_t imageIndex);
void cleanPipeline();
void cleanBuffers();
void cleanSyncObjects();
void cleanBase();
void cleanDescriptors();
void copyTransformedBufferToTextureImage();
QDomDocument openTintMapXML(QString filePath);
QVector<uint8_t> saveTintMapArrays(QDomDocument doc);
QVector<uint8_t> extractIntArrayFromString(QString input, QString delimiter);
void copyDataToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory, uint8_t* dataIn, VkDeviceSize dataSize);
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,
// VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
// VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME
};
const std::vector<Vertex> _vertices = {
{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}},
// {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
// {{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
// {{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
// {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}
};
const std::vector<uint32_t> _indices = {
0, 1, 2, 2, 3, 0,
// 4, 5, 6, 6, 7, 4
};
uint32_t currentFrame = 0;
bool framebufferResized = false;
GLFWwindow *_window;
// VulkanWindow _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;
VkImage _RawTextureImage;
VkDeviceMemory _RawTextureImageMemory;
VkImageView _RawTextureImageView;
VkImage _textureImage;
VkDeviceMemory _textureImageMemory;
VkImageView _textureImageView;
VkSampler _textureSampler;
VkImage _depthImage;
VkDeviceMemory _depthImageMemory;
VkImageView _depthImageView;
std::vector<VkBuffer> _shaderRawStorageBuffers;
std::vector<VkDeviceMemory> _shaderRawStorageBuffersMemory;
std::vector<VkBuffer> _shaderTransformedStorageBuffers;
std::vector<VkDeviceMemory> _shaderTransformedStorageBuffersMemory;
VkDeviceSize _textureImageSize;
uint32_t _textureImageWidth;
uint32_t _textureImageHeight;
VkPipelineLayout _computePipelineLayout;
VkPipeline _computePipeline;
VkDescriptorSetLayout _computeDescriptorSetLayout;
VkDescriptorPool _computeDescriptorPool;
std::vector<VkDescriptorSet> _computeDescriptorSets;
std::vector<VkCommandBuffer> _computeCommandBuffers;
std::vector<VkFence> _computeInFlightFences;
std::vector<VkSemaphore> _computeFinishedSemaphores;
std::vector<VkBuffer> _computeStorageBuffers;
std::vector<VkDeviceMemory> _computeStorageBuffersMemory;
// uint8_t* _tintMapArray;
VkDeviceSize _tintMapSize;
std::vector<VkBuffer> _computeUniformBuffers;
std::vector<VkDeviceMemory> _computeUniformBuffersMemory;
std::vector<void*> _computeUniformBuffersMapped;
};
#endif // COMPUTEANDGRAPHICS_H