diff --git a/VkTest.pro b/VkTest.pro index 937460b..de9dcda 100644 --- a/VkTest.pro +++ b/VkTest.pro @@ -1,4 +1,4 @@ -QT += +QT += core xml x11extras CONFIG += c++17 @@ -12,16 +12,19 @@ INCLUDEPATH += /usr/include/vulkan \ $$PWD/third_party/fmt/build LIBS += -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi \ + -L$$PWD/third_party/pugixml/build -lpugixml \ # -lSDL2main -lSDL2 -lvk-bootstrap \ # -L$$PWD/third_party/fmt/build -lfmt SOURCES += \ VulkanTutorial1.0/ComputeAndGraphics.cpp \ + VulkanTutorial1.0/VulkanWindow.cpp \ main.cpp HEADERS += \ \ VulkanTutorial1.0/ComputeAndGraphics.h \ - VulkanTutorial1.0/Types.h + VulkanTutorial1.0/Types.h \ + VulkanTutorial1.0/VulkanWindow.h DISTFILES += \ \ diff --git a/VkTest.pro.user b/VkTest.pro.user index 3d3a480..7914520 100644 --- a/VkTest.pro.user +++ b/VkTest.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -623,8 +623,8 @@ 0 - - + VkTest + VkTest Qt4ProjectManager.AndroidRunConfiguration:/home/ali-mehrabani/Qt_projects/VkTest/VkTest.pro 3768 diff --git a/VulkanTutorial1.0/ComputeAndGraphics.cpp b/VulkanTutorial1.0/ComputeAndGraphics.cpp index 9e0c3f5..15ad85f 100644 --- a/VulkanTutorial1.0/ComputeAndGraphics.cpp +++ b/VulkanTutorial1.0/ComputeAndGraphics.cpp @@ -59,15 +59,17 @@ void ComputeAndGraphics::initWindow() glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); _window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); - glfwSetWindowUserPointer(_window, this); - glfwSetFramebufferSizeCallback(_window, framebufferResizeCallback); -} +// glfwSetWindowUserPointer(_window, this); +// glfwSetFramebufferSizeCallback(_window, framebufferResizeCallback); -void ComputeAndGraphics::framebufferResizeCallback(GLFWwindow* window, int /*width*/, int /*height*/) { - auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); - app->framebufferResized = true; +// window = } +//void ComputeAndGraphics::framebufferResizeCallback(GLFWwindow* window, int /*width*/, int /*height*/) { +// auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); +// app->framebufferResized = true; +//} + void ComputeAndGraphics::initVulkan() @@ -97,7 +99,9 @@ void ComputeAndGraphics::initVulkan() createVertexBuffer(); createIndexBuffer(); createShaderStorageBuffers(); + createComputeStorageBuffers(); createUniformBuffers(); + createComputeUniformBuffers(); createDescriptorPool(); createComputeDescriptorPool(); createDescriptorSets(); @@ -138,10 +142,10 @@ VkApplicationInfo ComputeAndGraphics::createInstanceAppInfo() VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Vulkan App"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.applicationVersion = VK_MAKE_VERSION(1, 3, 0); appInfo.pEngineName = "No Engine"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.engineVersion = VK_MAKE_VERSION(1, 3, 0); + appInfo.apiVersion = VK_API_VERSION_1_3; return appInfo; } @@ -200,11 +204,14 @@ void ComputeAndGraphics::createInstance() std::vector ComputeAndGraphics::getRequiredExtensions() { - uint32_t glfwExtensionCount = 0; - const char** glfwExtensions; - glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector extensions; + extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); +#ifdef Q_OS_LINUX + extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); +#elif Q_OS_ANDROID + extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); +#endif if (enableValidationLayers) { extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); @@ -297,6 +304,7 @@ bool ComputeAndGraphics::checkDeviceExtensionSupport(VkPhysicalDevice device) { std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); for (const auto& extension : availableExtensions) { +// qDebug() << extension.extensionName; requiredExtensions.erase(extension.extensionName); } @@ -371,8 +379,13 @@ void ComputeAndGraphics::createLogicalDevice() queueCreateInfos.push_back(createQueueInfo(queueFamily, 1, &queuePriority)); } - VkPhysicalDeviceFeatures deviceFeatures = createDeviceFeatures(); - VkDeviceCreateInfo createInfo = createLogicalDeviceInfo(queueCreateInfos, &deviceFeatures); + VkPhysicalDeviceFeatures deviceFeatures = createDeviceCoreFeatures(); + + VkPhysicalDeviceVulkan12Features deviceFeatures12 = createDeviceVulkan12Features(nullptr); +// VkPhysicalDevice8BitStorageFeaturesKHR device8BitStorageFeatures2Info = createDevice8BitStorageFeatures2Info(); +// VkPhysicalDeviceFeatures2 deviceCoreFeatures2 = createDeviceCoreFeatures2(&device8BitStorageFeatures2Info); + + VkDeviceCreateInfo createInfo = createLogicalDeviceInfo(queueCreateInfos, &deviceFeatures, &deviceFeatures12); if (vkCreateDevice(_physicalDevice, &createInfo, nullptr, &_device) != VK_SUCCESS) { throw std::runtime_error("failed to create logical device!"); @@ -393,7 +406,7 @@ VkDeviceQueueCreateInfo ComputeAndGraphics::createQueueInfo(uint32_t queueFamily return queueCreateInfo; } -VkPhysicalDeviceFeatures ComputeAndGraphics::createDeviceFeatures() +VkPhysicalDeviceFeatures ComputeAndGraphics::createDeviceCoreFeatures() { VkPhysicalDeviceFeatures deviceFeatures{}; deviceFeatures.samplerAnisotropy = VK_TRUE; @@ -401,8 +414,51 @@ VkPhysicalDeviceFeatures ComputeAndGraphics::createDeviceFeatures() return deviceFeatures; } +VkPhysicalDeviceVulkan12Features ComputeAndGraphics::createDeviceVulkan12Features(void* pNext) +{ + VkPhysicalDeviceVulkan12Features deviceFeatures12{}; + deviceFeatures12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + deviceFeatures12.scalarBlockLayout = VK_TRUE; + deviceFeatures12.shaderInt8 = VK_TRUE; + deviceFeatures12.uniformAndStorageBuffer8BitAccess = VK_TRUE; +// deviceFeatures12.storageBuffer8BitAccess = VK_TRUE; +// deviceFeatures12.storagePushConstant8 = VK_TRUE; + deviceFeatures12.pNext = pNext; + + return deviceFeatures12; +} + +VkPhysicalDeviceVulkan13Features ComputeAndGraphics::createDeviceVulkan13Features(void* pNext) +{ + VkPhysicalDeviceVulkan13Features deviceFeatures13{}; + deviceFeatures13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + deviceFeatures13.pNext = pNext; + + return deviceFeatures13; +} + +VkPhysicalDeviceFeatures2 ComputeAndGraphics::createDeviceCoreFeatures2(VkPhysicalDevice8BitStorageFeatures* pNext) +{ + VkPhysicalDeviceFeatures2 deviceFeatures2{}; + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + deviceFeatures2.pNext = pNext; + + return deviceFeatures2; +} + +VkPhysicalDevice8BitStorageFeaturesKHR ComputeAndGraphics::createDevice8BitStorageFeatures2Info() +{ + VkPhysicalDevice8BitStorageFeatures storage8BitFeatures{}; + storage8BitFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES; + storage8BitFeatures.uniformAndStorageBuffer8BitAccess = VK_TRUE; + storage8BitFeatures.storagePushConstant8 = VK_TRUE; + storage8BitFeatures.storageBuffer8BitAccess = VK_TRUE; + + return storage8BitFeatures; +} + VkDeviceCreateInfo ComputeAndGraphics::createLogicalDeviceInfo(std::vector& queueCreateInfos - , VkPhysicalDeviceFeatures* deviceFeatures) + , VkPhysicalDeviceFeatures* deviceFeatures, void* pNext) { VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -411,6 +467,7 @@ VkDeviceCreateInfo ComputeAndGraphics::createLogicalDeviceInfo(std::vector(deviceExtensions.size()); createInfo.ppEnabledExtensionNames = deviceExtensions.data(); @@ -655,7 +712,9 @@ void ComputeAndGraphics::createComputeDescriptorSetLayout() { VkDescriptorSetLayoutBinding computeLayoutBinding2 = createLayoutBindingInfo(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); - std::vector bindings = {uboLayoutBinding, computeLayoutBinding1, computeLayoutBinding2}; + VkDescriptorSetLayoutBinding computeLayoutBinding3 = createLayoutBindingInfo(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); + + std::vector bindings = {uboLayoutBinding, computeLayoutBinding1, computeLayoutBinding2, computeLayoutBinding3}; VkDescriptorSetLayoutCreateInfo layoutInfo{}; layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.bindingCount = static_cast(bindings.size()); @@ -1037,7 +1096,7 @@ void ComputeAndGraphics::createTextureImage() { stbi_image_free(pixels); - createImage(texWidth, texHeight, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_LINEAR + createImage(texWidth, texHeight, 1, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL , VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _textureImage, _textureImageMemory); @@ -1269,9 +1328,9 @@ void ComputeAndGraphics::createTextureSampler() samplerInfo.compareEnable = VK_FALSE; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 1.0; +// samplerInfo.mipLodBias = 0.0f; +// samplerInfo.minLod = 0.0f; +// samplerInfo.maxLod = 1.0; if (vkCreateSampler(_device, &samplerInfo, nullptr, &_textureSampler) != VK_SUCCESS) { throw std::runtime_error("failed to create texture sampler!"); @@ -1307,7 +1366,6 @@ void ComputeAndGraphics::copyVerticesToStagingBuffer(VkBuffer& stagingBuffer, Vk vkUnmapMemory(_device, stagingBufferMemory); } - void ComputeAndGraphics::createIndexBuffer() { VkDeviceSize bufferSize = sizeof(_indices[0]) * _indices.size(); @@ -1459,13 +1517,104 @@ void ComputeAndGraphics::initShaderStorageBuffers(VkBuffer& stagingBuffer, VkDev _shaderTransformedStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT); for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderRawStorageBuffers[i], _shaderRawStorageBuffersMemory[i]); copyBuffer(stagingBuffer, _shaderRawStorageBuffers[i], bufferSize); - createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT - , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderTransformedStorageBuffers[i], _shaderTransformedStorageBuffersMemory[i]); - copyBuffer(stagingBuffer, _shaderTransformedStorageBuffers[i], bufferSize); + createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _shaderTransformedStorageBuffers[i], _shaderTransformedStorageBuffersMemory[i]); +// copyBuffer(stagingBuffer, _shaderTransformedStorageBuffers[i], bufferSize); + } +} + +void ComputeAndGraphics::createComputeStorageBuffers() +{ + QString filePath = "/home/ali-mehrabani/Qt_projects/VkTest/misc/TintMap.xml"; + QDomDocument doc = openTintMapXML(filePath); + + QVector tintMap = saveTintMapArrays(doc); + _tintMapSize = 11 * 256 * 3; + + VkBuffer stagingBuffer; + VkDeviceMemory stagingBufferMemory; + copyDataToStagingBuffer(stagingBuffer, stagingBufferMemory, tintMap.data(), _tintMapSize); + + initComputeStorageBuffers(stagingBuffer, _tintMapSize); + + vkDestroyBuffer(_device, stagingBuffer, nullptr); + vkFreeMemory(_device, stagingBufferMemory, nullptr); +} + +void ComputeAndGraphics::copyDataToStagingBuffer(VkBuffer& stagingBuffer, VkDeviceMemory& stagingBufferMemory, uint8_t* dataIn, VkDeviceSize dataSize) +{ + createBuffer(dataSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + , stagingBuffer, stagingBufferMemory); + + void* data; + vkMapMemory(_device, stagingBufferMemory, 0, dataSize, 0, &data); + memcpy(data, dataIn, static_cast(dataSize)); + vkUnmapMemory(_device, stagingBufferMemory); +} + +QVector ComputeAndGraphics::saveTintMapArrays(QDomDocument doc) +{ + QDomElement root = doc.documentElement(); + + QDomNodeList entities = root.childNodes(); + + QVector data; + for (int i = 0; i < entities.count(); ++i) { + QDomNodeList fields = entities.at(i).childNodes(); + QString mappings = fields.at(1).toElement().attribute("value"); + QVector mappingsArray = extractIntArrayFromString(mappings, ";"); + data.append(mappingsArray); + } + + return data; +} + +QVector ComputeAndGraphics::extractIntArrayFromString(QString input, QString delimiter) +{ + QVector result; + + QStringList pixels = input.split(delimiter); + for (int i = 0; i < pixels.count(); ++i) { + QStringList rgb = pixels.at(i).split(","); + for (int j = 0; j < rgb.count(); ++j) { + result.append(static_cast(rgb.at(j).toUInt())); + } +// result.append(static_cast(1)); + } + + return result; +} + +QDomDocument ComputeAndGraphics::openTintMapXML(QString filePath) +{ + QFile file(filePath); + QDomDocument doc; + + if (!file.open(QIODevice::ReadOnly)) { + qDebug() << "Failed to open file:" << filePath; + } else + { + if (!doc.setContent(&file)) { + qDebug() << "Failed to parse XML file."; + } + file.close(); + } + return doc; +} + +void ComputeAndGraphics::initComputeStorageBuffers(VkBuffer& stagingBuffer, VkDeviceSize bufferSize) +{ + _computeStorageBuffers.resize(MAX_FRAMES_IN_FLIGHT); + _computeStorageBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT); + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + createBuffer(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT + , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _computeStorageBuffers[i], _computeStorageBuffersMemory[i]); + copyBuffer(stagingBuffer, _computeStorageBuffers[i], bufferSize); } } @@ -1484,6 +1633,21 @@ void ComputeAndGraphics::createUniformBuffers() { } } +void ComputeAndGraphics::createComputeUniformBuffers() { + VkDeviceSize bufferSize = sizeof(ComputeParameters); + + _computeUniformBuffers.resize(MAX_FRAMES_IN_FLIGHT); + _computeUniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT); + _computeUniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT); + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + , _computeUniformBuffers[i], _computeUniformBuffersMemory[i]); + + vkMapMemory(_device, _computeUniformBuffersMemory[i], 0, bufferSize, 0, &_computeUniformBuffersMapped[i]); + } +} + void ComputeAndGraphics::createDescriptorPool() { std::array poolSizes{}; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -1507,7 +1671,7 @@ void ComputeAndGraphics::createComputeDescriptorPool() { poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; poolSizes[0].descriptorCount = static_cast(MAX_FRAMES_IN_FLIGHT); poolSizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - poolSizes[1].descriptorCount = static_cast(MAX_FRAMES_IN_FLIGHT) * 2; + poolSizes[1].descriptorCount = static_cast(MAX_FRAMES_IN_FLIGHT) * 3; VkDescriptorPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; @@ -1603,9 +1767,9 @@ void ComputeAndGraphics::createComputeDescriptorSets() allocateComputeDescriptorSets(); for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - VkDescriptorBufferInfo bufferInfo = createDescriptorBufferInfo(_uniformBuffers[i], sizeof(UniformBufferObject)); + VkDescriptorBufferInfo bufferInfo = createDescriptorBufferInfo(_computeUniformBuffers[i], sizeof(ComputeParameters)); - std::array descriptorWrites{}; + std::array descriptorWrites{}; addUniformBufferWriteDescriptor(descriptorWrites[0], &bufferInfo, _computeDescriptorSets[i], 0); @@ -1615,6 +1779,9 @@ void ComputeAndGraphics::createComputeDescriptorSets() VkDescriptorBufferInfo storageBufferInfoCurrentFrame = createDescriptorBufferInfo(_shaderTransformedStorageBuffers[i], _textureImageSize); addStorageBufferWriteDescriptor(descriptorWrites[2], &storageBufferInfoCurrentFrame, _computeDescriptorSets[i], 2); + VkDescriptorBufferInfo computeBufferInfo = createDescriptorBufferInfo(_computeStorageBuffers[i], _tintMapSize); + addStorageBufferWriteDescriptor(descriptorWrites[3], &computeBufferInfo, _computeDescriptorSets[i], 3); + vkUpdateDescriptorSets(_device, static_cast(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); } } @@ -1740,6 +1907,8 @@ void ComputeAndGraphics::computeSubmission() { vkWaitForFences(_device, 1, &_computeInFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + updateComputeUniformBuffer(currentFrame); + vkResetFences(_device, 1, &_computeInFlightFences[currentFrame]); vkResetCommandBuffer(_computeCommandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0); @@ -1948,7 +2117,9 @@ void ComputeAndGraphics::recordComputeCommandBuffer(VkCommandBuffer commandBuffe vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, _computePipelineLayout, 0, 1, &_computeDescriptorSets[currentFrame], 0, nullptr); - vkCmdDispatch(commandBuffer, static_cast(_textureImageSize / 8), 1, 1); + vkCmdDispatch(commandBuffer, static_cast((_textureImageSize) / 256) + , 1 + , 1); if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { throw std::runtime_error("failed to record compute command buffer!"); @@ -1964,13 +2135,21 @@ void ComputeAndGraphics::updateUniformBuffer(uint32_t currentImage) { UniformBufferObject ubo{}; ubo.model = glm::rotate(glm::mat4(1.0f), glm::radians(0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); - ubo.view = glm::lookAt(glm::vec3(0.001f, 0.001f, 1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.view = glm::lookAt(glm::vec3(0.0f, 0.00001f, 1.5f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ubo.proj = glm::perspective(glm::radians(45.0f), _swapChainExtent.width / static_cast(_swapChainExtent.height), 0.1f, 10.0f); ubo.proj[1][1] *= -1; memcpy(_uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } +void ComputeAndGraphics::updateComputeUniformBuffer(uint32_t currentImage) +{ + ComputeParameters ubo{}; + ubo.tintMapType = 4; + + memcpy(_computeUniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); +} + void ComputeAndGraphics::recreateSwapChain() { int width = 0, height = 0; glfwGetFramebufferSize(_window, &width, &height); @@ -2022,13 +2201,20 @@ void ComputeAndGraphics::cleanBuffers() for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vkDestroyBuffer(_device, _shaderRawStorageBuffers[i], nullptr); vkFreeMemory(_device, _shaderRawStorageBuffersMemory[i], nullptr); + vkDestroyBuffer(_device, _shaderTransformedStorageBuffers[i], nullptr); vkFreeMemory(_device, _shaderTransformedStorageBuffersMemory[i], nullptr); + + vkDestroyBuffer(_device, _computeStorageBuffers[i], nullptr); + vkFreeMemory(_device, _computeStorageBuffersMemory[i], nullptr); } for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { vkDestroyBuffer(_device, _uniformBuffers[i], nullptr); vkFreeMemory(_device, _uniformBuffersMemory[i], nullptr); + + vkDestroyBuffer(_device, _computeUniformBuffers[i], nullptr); + vkFreeMemory(_device, _computeUniformBuffersMemory[i], nullptr); } vkDestroyBuffer(_device, _indexBuffer, nullptr); diff --git a/VulkanTutorial1.0/ComputeAndGraphics.h b/VulkanTutorial1.0/ComputeAndGraphics.h index 434877e..eb4cbda 100644 --- a/VulkanTutorial1.0/ComputeAndGraphics.h +++ b/VulkanTutorial1.0/ComputeAndGraphics.h @@ -10,10 +10,9 @@ #endif #include "Types.h" +#include "VulkanWindow.h" #include - - #include #include // Necessary for uint32_t #include // Necessary for std::numeric_limits @@ -21,11 +20,9 @@ #include #include -#ifdef Q_OS_ANDROID - const QString TARGET_PLATFORM = "Android"; -#else - const QString TARGET_PLATFORM = "Linux"; -#endif +#include +#include +#include const int MAX_FRAMES_IN_FLIGHT = 2; @@ -38,6 +35,10 @@ struct QueueFamilyIndices { } }; +struct ComputeParameters { + alignas(16) glm::uint32 tintMapType; +}; + struct Vertex { alignas(16) glm::vec3 pos; alignas(16) glm::vec3 color; @@ -100,7 +101,7 @@ public: } static std::vector readFile(const std::string& filename); - static void framebufferResizeCallback(GLFWwindow* window, int width, int height); +// static void framebufferResizeCallback(GLFWwindow* window, int width, int height); // static void framebufferResizeCallback(QQuickWindow* window, int width, int height); private: @@ -186,14 +187,25 @@ private: 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& extensions , VkDebugUtilsMessengerCreateInfoEXT& debugCreateInfo); VkDeviceQueueCreateInfo createQueueInfo(uint32_t queueFamily, uint32_t queueCount, float* queuePriority); - VkPhysicalDeviceFeatures createDeviceFeatures(); - VkDeviceCreateInfo createLogicalDeviceInfo(std::vector& queueCreateInfos, VkPhysicalDeviceFeatures* deviceFeatures); + VkPhysicalDeviceFeatures createDeviceCoreFeatures(); + VkPhysicalDeviceVulkan12Features createDeviceVulkan12Features(void* pNext); + VkPhysicalDeviceVulkan13Features createDeviceVulkan13Features(void* pNext); + VkPhysicalDeviceFeatures2KHR createDeviceCoreFeatures2(VkPhysicalDevice8BitStorageFeaturesKHR* pNext); + VkPhysicalDevice8BitStorageFeaturesKHR createDevice8BitStorageFeatures2Info(); + VkDeviceCreateInfo createLogicalDeviceInfo(std::vector& queueCreateInfos, VkPhysicalDeviceFeatures* deviceFeatures + , void* pNext); VkSwapchainCreateInfoKHR createSwapChainInfo(SwapChainSupportDetails swapChainSupport, VkSurfaceKHR _surface, uint32_t imageCount , VkSurfaceFormatKHR surfaceFormat, VkExtent2D extent, VkPresentModeKHR presentMode); @@ -268,6 +280,11 @@ private: void copyTransformedBufferToTextureImage(); + QDomDocument openTintMapXML(QString filePath); + QVector saveTintMapArrays(QDomDocument doc); + QVector 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; @@ -275,7 +292,9 @@ private: "VK_LAYER_KHRONOS_validation" }; const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME + VK_KHR_SWAPCHAIN_EXTENSION_NAME, +// VK_KHR_8BIT_STORAGE_EXTENSION_NAME, +// VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME }; const std::vector _vertices = { {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}}, @@ -297,7 +316,7 @@ private: bool framebufferResized = false; GLFWwindow *_window; -// QQuickWindow* _window; +// VulkanWindow _window; VkInstance _instance; VkDebugUtilsMessengerEXT _debugMessenger; VkPhysicalDevice _physicalDevice; @@ -361,6 +380,15 @@ private: std::vector _computeInFlightFences; std::vector _computeFinishedSemaphores; + std::vector _computeStorageBuffers; + std::vector _computeStorageBuffersMemory; +// uint8_t* _tintMapArray; + VkDeviceSize _tintMapSize; + + std::vector _computeUniformBuffers; + std::vector _computeUniformBuffersMemory; + std::vector _computeUniformBuffersMapped; + }; #endif // COMPUTEANDGRAPHICS_H diff --git a/VulkanTutorial1.0/Types.h b/VulkanTutorial1.0/Types.h index 5e28240..d7578be 100644 --- a/VulkanTutorial1.0/Types.h +++ b/VulkanTutorial1.0/Types.h @@ -8,10 +8,10 @@ #pragma once -#define VK_USE_PLATFORM_ +//#define VK_USE_PLATFORM_ #define GLFW_INCLUDE_VULKAN #include -#define GLFW_EXPOSE_NATIVE_ +//#define GLFW_EXPOSE_NATIVE_ #include #define GLM_FORCE_RADIANS @@ -25,6 +25,12 @@ #include +#ifdef Q_OS_ANDROID + const QString TARGET_PLATFORM = "Android"; +#else + const QString TARGET_PLATFORM = "Linux"; +#endif + struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; std::vector formats; diff --git a/VulkanTutorial1.0/VulkanWindow.cpp b/VulkanTutorial1.0/VulkanWindow.cpp new file mode 100644 index 0000000..7547bfd --- /dev/null +++ b/VulkanTutorial1.0/VulkanWindow.cpp @@ -0,0 +1,49 @@ +#include "VulkanWindow.h" + +VulkanWindow::VulkanWindow() +{ +// setSurfaceType(QWindow::VulkanSurface); +// if (!initVulkanInstance()) { +// qCritical() << "Failed to initialize Vulkan instance!"; +// exit(EXIT_FAILURE); +// } + createVulkanSurface(); +} + +VulkanWindow::~VulkanWindow() { +// cleanup(); +} + +void VulkanWindow::createVulkanSurface() { + VkSurfaceKHR surface; + +#ifdef Q_OS_LINUX + VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {}; + surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + surfaceCreateInfo.connection = QX11Info::connection(); + surfaceCreateInfo.window = static_cast(winId()); + + if (vkCreateXcbSurfaceKHR(_instance, &surfaceCreateInfo, nullptr, &surface) != VK_SUCCESS) { + qCritical() << "Failed to create Vulkan surface on Linux."; + exit(EXIT_FAILURE); + } +#elif Q_OS_ANDROID + VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {}; + surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + surfaceCreateInfo.window = reinterpret_cast(winId()); + + if (vkCreateAndroidSurfaceKHR(_instance, &surfaceCreateInfo, nullptr, &surface) != VK_SUCCESS) { + qCritical() << "Failed to create Vulkan surface on Android."; + exit(EXIT_FAILURE); + } +#endif + _surface = surface; + qDebug() << "Vulkan surface created successfully."; + +} + +void VulkanWindow::cleanup() { + if (_surface != VK_NULL_HANDLE) { + vkDestroySurfaceKHR(_instance, _surface, nullptr); + } +} diff --git a/VulkanTutorial1.0/VulkanWindow.h b/VulkanTutorial1.0/VulkanWindow.h new file mode 100644 index 0000000..308395d --- /dev/null +++ b/VulkanTutorial1.0/VulkanWindow.h @@ -0,0 +1,37 @@ +#ifndef VULKANWINDOW_H +#define VULKANWINDOW_H + +#include +#include +#include +#include + +#include "Types.h" + +#ifdef Q_OS_ANDROID +#include +#else +#include +#endif + + +#define VK_USE_PLATFORM_XCB_KHR // Enable Vulkan support for Linux (XCB) +#define VK_USE_PLATFORM_ANDROID_KHR // Enable Vulkan support for Android + +class VulkanWindow : public QWindow +{ + Q_OBJECT + +public: + VulkanWindow(); + virtual ~VulkanWindow(); + +private: + void createVulkanSurface(); + void cleanup(); + + VkSurfaceKHR _surface; + VkInstance _instance; +}; + +#endif // VULKANWINDOW_H diff --git a/misc/TintMap.xml b/misc/TintMap.xml new file mode 100644 index 0000000..64e4e6d --- /dev/null +++ b/misc/TintMap.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/shaders/VulkanTutorial1.0/ComputeAndGraphics/compComp.spv b/shaders/VulkanTutorial1.0/ComputeAndGraphics/compComp.spv index 848ba5b..761540a 100644 Binary files a/shaders/VulkanTutorial1.0/ComputeAndGraphics/compComp.spv and b/shaders/VulkanTutorial1.0/ComputeAndGraphics/compComp.spv differ diff --git a/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.comp b/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.comp index 1af5f3d..edda1af 100644 --- a/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.comp +++ b/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.comp @@ -1,26 +1,48 @@ #version 450 +#extension GL_EXT_shader_8bit_storage : require +#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require +#extension GL_EXT_scalar_block_layout : require + +//#define GL_EXT_shader_8bit_storage 1 + +struct ComputeParameters { + uint8_t tintMapType; +}; + layout (binding = 0) uniform ParameterUBO { - float deltaTime; + ComputeParameters params; } ubo; -layout(std140, binding = 1) readonly buffer TexelSSBOIn { - vec4 texelsIn[]; +layout(std430, binding = 1) readonly buffer TexelSSBOIn { + u8vec4 texelsIn[]; }; -layout(std140, binding = 2) buffer TexelSSBOOut { - vec4 texelsOut[]; +layout(std430, binding = 2) buffer TexelSSBOOut { + u8vec4 texelsOut[]; }; -layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in; +layout(scalar, binding = 3) readonly buffer ComputeSSBOIn { + u8vec3 tintMapIn[]; +}; + +layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in; + + void main() { uint idx = gl_GlobalInvocationID.x; - vec4 texelIn = texelsIn[idx]; + u8vec4 texelIn = texelsIn[idx]; + + // Grayscale code +// float gray = dot(vec3(texelIn.rgb), vec3(0.2627, 0.6780, 0.0593)); +// texelsOut[idx] = u8vec4(u8vec3(gray), 1.0); - float gray = dot(texelIn.rgb, vec3(0.2627, 0.6780, 0.0593)); - texelsOut[idx] = vec4(vec3(gray), 1.0); + // TintMap code + uint8_t gray = uint8_t(dot(vec3(texelIn.rgb), vec3(0.2627, 0.6780, 0.0593))); + texelsOut[idx] = u8vec4(tintMapIn[ubo.params.tintMapType * 256 + gray], 1.0); +// texelsOut[idx] = u8vec4(tintMapIn[191], 1.0); } diff --git a/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.vert b/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.vert index 24f0cb2..151e5e4 100644 --- a/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.vert +++ b/shaders/VulkanTutorial1.0/ComputeAndGraphics/shaderCompute.vert @@ -14,7 +14,6 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoord; void main() { - gl_Position = vec4(inPosition, 1.0); gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); // gl_Position = vec4(inPosition, 1.0); diff --git a/shaders/VulkanTutorial1.0/ComputeAndGraphics/vertComp.spv b/shaders/VulkanTutorial1.0/ComputeAndGraphics/vertComp.spv index 91aaf20..50fbc24 100644 Binary files a/shaders/VulkanTutorial1.0/ComputeAndGraphics/vertComp.spv and b/shaders/VulkanTutorial1.0/ComputeAndGraphics/vertComp.spv differ