AliMehrabani
4 weeks ago
23 changed files with 1349 additions and 163 deletions
@ -1,2 +1,4 @@ |
|||
.gradle/ |
|||
build/ |
|||
third_party/ |
|||
glm/ |
|||
|
@ -0,0 +1,29 @@ |
|||
QMAKE_CXX.QT_COMPILER_STDCXX = 201402L |
|||
QMAKE_CXX.QMAKE_CLANG_MAJOR_VERSION = 8 |
|||
QMAKE_CXX.QMAKE_CLANG_MINOR_VERSION = 0 |
|||
QMAKE_CXX.QMAKE_CLANG_PATCH_VERSION = 7 |
|||
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 4 |
|||
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 2 |
|||
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 1 |
|||
QMAKE_CXX.COMPILER_MACROS = \ |
|||
QT_COMPILER_STDCXX \ |
|||
QMAKE_CLANG_MAJOR_VERSION \ |
|||
QMAKE_CLANG_MINOR_VERSION \ |
|||
QMAKE_CLANG_PATCH_VERSION \ |
|||
QMAKE_GCC_MAJOR_VERSION \ |
|||
QMAKE_GCC_MINOR_VERSION \ |
|||
QMAKE_GCC_PATCH_VERSION |
|||
QMAKE_CXX.INCDIRS = \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/sysroot/usr/include/aarch64-linux-android \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/sources/cxx-stl/llvm-libc++/include \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/sources/android/support/include \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/sources/cxx-stl/llvm-libc++abi/include \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.7/include \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/sysroot/usr/include |
|||
QMAKE_CXX.LIBDIRS = \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.7 \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.7/lib/linux/aarch64 \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/lib/gcc/aarch64-linux-android/4.9.x \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/aarch64-linux-android/lib64 \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/aarch64-linux-android/lib \ |
|||
/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/platforms/android-21/arch-arm64/usr/lib |
@ -0,0 +1,6 @@ |
|||
#include "VkDescriptors.h" |
|||
|
|||
VkDescriptors::VkDescriptors() |
|||
{ |
|||
|
|||
} |
@ -0,0 +1,12 @@ |
|||
#ifndef VKDESCRIPTORS_H |
|||
#define VKDESCRIPTORS_H |
|||
|
|||
#include <QObject> |
|||
|
|||
class VkDescriptors |
|||
{ |
|||
public: |
|||
VkDescriptors(); |
|||
}; |
|||
|
|||
#endif // VKDESCRIPTORS_H
|
@ -0,0 +1,402 @@ |
|||
#include "VkEngine.h" |
|||
|
|||
#include <SDL.h> |
|||
#include <SDL_vulkan.h> |
|||
|
|||
#include <VkInitializers.h> |
|||
#include <VkTypes.h> |
|||
|
|||
//bootstrap library
|
|||
#include "VkBootstrap.h" |
|||
#include "VkImages.h" |
|||
|
|||
#define VMA_IMPLEMENTATION |
|||
#include "vma/vk_mem_alloc.h" |
|||
|
|||
#include <chrono> |
|||
#include <thread> |
|||
//< includes
|
|||
|
|||
//> init
|
|||
constexpr bool bUseValidationLayers = false; |
|||
|
|||
VkEngine* loadedEngine = nullptr; |
|||
|
|||
VkEngine::VkEngine() |
|||
{ |
|||
|
|||
} |
|||
|
|||
VkEngine& VkEngine::Get() |
|||
{ |
|||
return *loadedEngine; |
|||
} |
|||
|
|||
void VkEngine::init() |
|||
{ |
|||
// only one engine initialization is allowed with the application.
|
|||
assert(loadedEngine == nullptr); |
|||
loadedEngine = this; |
|||
|
|||
// We initialize SDL and create a window with it.
|
|||
SDL_Init(SDL_INIT_VIDEO); |
|||
|
|||
SDL_WindowFlags window_flags = static_cast<SDL_WindowFlags>(SDL_WINDOW_VULKAN); |
|||
|
|||
_window = SDL_CreateWindow( |
|||
"Vulkan Engine", |
|||
SDL_WINDOWPOS_UNDEFINED, |
|||
SDL_WINDOWPOS_UNDEFINED, |
|||
_windowExtent.width, |
|||
_windowExtent.height, |
|||
window_flags); |
|||
|
|||
init_vulkan(); |
|||
|
|||
init_swapchain(); |
|||
|
|||
init_commands(); |
|||
|
|||
init_sync_structures(); |
|||
|
|||
// everything went fine
|
|||
_isInitialized = true; |
|||
} |
|||
|
|||
void VkEngine::cleanup() |
|||
{ |
|||
if (_isInitialized) { |
|||
|
|||
vkDeviceWaitIdle(_device); |
|||
|
|||
for (int i = 0; i < static_cast<int>(FRAME_OVERLAP); i++) |
|||
{ |
|||
//already written from before
|
|||
vkDestroyCommandPool(_device, _frames[i]._commandPool, nullptr); |
|||
|
|||
//destroy sync objects
|
|||
vkDestroyFence(_device, _frames[i]._renderFence, nullptr); |
|||
vkDestroySemaphore(_device, _frames[i]._renderSemaphore, nullptr); |
|||
vkDestroySemaphore(_device ,_frames[i]._swapchainSemaphore, nullptr); |
|||
|
|||
_frames[i]._deletionQueue.flush(); |
|||
} |
|||
|
|||
_mainDeletionQueue.flush(); |
|||
|
|||
vkDeviceWaitIdle(_device); |
|||
|
|||
for (int i = 0; i < static_cast<int>(FRAME_OVERLAP); i++) { |
|||
vkDestroyCommandPool(_device, _frames[i]._commandPool, nullptr); |
|||
} |
|||
|
|||
destroy_swapchain(); |
|||
|
|||
vkDestroySurfaceKHR(_instance, _surface, nullptr); |
|||
vkDestroyDevice(_device, nullptr); |
|||
|
|||
vkb::destroy_debug_utils_messenger(_instance, _debug_messenger); |
|||
vkDestroyInstance(_instance, nullptr); |
|||
SDL_DestroyWindow(_window); |
|||
} |
|||
|
|||
// clear engine pointer
|
|||
loadedEngine = nullptr; |
|||
} |
|||
|
|||
void VkEngine::draw() |
|||
{ |
|||
// wait until the gpu has finished rendering the last frame. Timeout of 1
|
|||
// second
|
|||
VK_CHECK(vkWaitForFences(_device, 1, &get_current_frame()._renderFence, true, 1000000000)); |
|||
|
|||
get_current_frame()._deletionQueue.flush(); |
|||
|
|||
VK_CHECK(vkResetFences(_device, 1, &get_current_frame()._renderFence)); |
|||
|
|||
uint32_t swapchainImageIndex; |
|||
VK_CHECK(vkAcquireNextImageKHR(_device, _swapchain, 1000000000, get_current_frame()._swapchainSemaphore, nullptr, &swapchainImageIndex)); |
|||
|
|||
//naming it cmd for shorter writing
|
|||
VkCommandBuffer cmd = get_current_frame()._mainCommandBuffer; |
|||
|
|||
// now that we are sure that the commands finished executing, we can safely
|
|||
// reset the command buffer to begin recording again.
|
|||
VK_CHECK(vkResetCommandBuffer(cmd, 0)); |
|||
|
|||
//begin the command buffer recording. We will use this command buffer exactly once, so we want to let vulkan know that
|
|||
VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); |
|||
|
|||
//start the command buffer recording
|
|||
VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); |
|||
|
|||
//make the swapchain image into writeable mode before rendering
|
|||
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); |
|||
|
|||
//make a clear-color from frame number. This will flash with a 120 frame period.
|
|||
VkClearColorValue clearValue; |
|||
float flash = std::abs(std::sin(_frameNumber / 120.f)); |
|||
clearValue = { { 0.0f, 0.0f, flash, 1.0f } }; |
|||
|
|||
VkImageSubresourceRange clearRange = vkinit::image_subresource_range(VK_IMAGE_ASPECT_COLOR_BIT); |
|||
|
|||
//clear image
|
|||
vkCmdClearColorImage(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange); |
|||
|
|||
//make the swapchain image into presentable mode
|
|||
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex],VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); |
|||
|
|||
//finalize the command buffer (we can no longer add commands, but it can now be executed)
|
|||
VK_CHECK(vkEndCommandBuffer(cmd)); |
|||
|
|||
//prepare the submission to the queue.
|
|||
//we want to wait on the _presentSemaphore, as that semaphore is signaled when the swapchain is ready
|
|||
//we will signal the _renderSemaphore, to signal that rendering has finished
|
|||
|
|||
VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd); |
|||
|
|||
VkSemaphoreSubmitInfo waitInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,get_current_frame()._swapchainSemaphore); |
|||
VkSemaphoreSubmitInfo signalInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT, get_current_frame()._renderSemaphore); |
|||
|
|||
VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo,&signalInfo,&waitInfo); |
|||
|
|||
//submit command buffer to the queue and execute it.
|
|||
// _renderFence will now block until the graphic commands finish execution
|
|||
VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, get_current_frame()._renderFence)); |
|||
|
|||
//prepare present
|
|||
// this will put the image we just rendered to into the visible window.
|
|||
// we want to wait on the _renderSemaphore for that,
|
|||
// as its necessary that drawing commands have finished before the image is displayed to the user
|
|||
VkPresentInfoKHR presentInfo = {}; |
|||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; |
|||
presentInfo.pNext = nullptr; |
|||
presentInfo.pSwapchains = &_swapchain; |
|||
presentInfo.swapchainCount = 1; |
|||
|
|||
presentInfo.pWaitSemaphores = &get_current_frame()._renderSemaphore; |
|||
presentInfo.waitSemaphoreCount = 1; |
|||
|
|||
presentInfo.pImageIndices = &swapchainImageIndex; |
|||
|
|||
VK_CHECK(vkQueuePresentKHR(_graphicsQueue, &presentInfo)); |
|||
|
|||
//increase the number of frames drawn
|
|||
_frameNumber++; |
|||
} |
|||
//< extras
|
|||
|
|||
//> drawloop
|
|||
void VkEngine::run() |
|||
{ |
|||
SDL_Event e; |
|||
bool bQuit = false; |
|||
|
|||
// main loop
|
|||
while (!bQuit) { |
|||
// Handle events on queue
|
|||
while (SDL_PollEvent(&e) != 0) { |
|||
// close the window when user alt-f4s or clicks the X button
|
|||
if (e.type == SDL_QUIT) |
|||
bQuit = true; |
|||
|
|||
if (e.type == SDL_WINDOWEVENT) { |
|||
if (e.window.event == SDL_WINDOWEVENT_MINIMIZED) { |
|||
stop_rendering = true; |
|||
} |
|||
if (e.window.event == SDL_WINDOWEVENT_RESTORED) { |
|||
stop_rendering = false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// do not draw if we are minimized
|
|||
if (stop_rendering) { |
|||
// throttle the speed to avoid the endless spinning
|
|||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); |
|||
continue; |
|||
} |
|||
|
|||
draw(); |
|||
} |
|||
} |
|||
|
|||
void VkEngine::init_vulkan() |
|||
{ |
|||
vkb::InstanceBuilder builder; |
|||
|
|||
//make the vulkan instance, with basic debug features
|
|||
auto inst_ret = builder.set_app_name("Example Vulkan Application") |
|||
.request_validation_layers(bUseValidationLayers) |
|||
.use_default_debug_messenger() |
|||
.require_api_version(1, 3, 0) |
|||
.build(); |
|||
|
|||
vkb::Instance vkb_inst = inst_ret.value(); |
|||
|
|||
//grab the instance
|
|||
_instance = vkb_inst.instance; |
|||
_debug_messenger = vkb_inst.debug_messenger; |
|||
|
|||
SDL_Vulkan_CreateSurface(_window, _instance, &_surface); |
|||
|
|||
//vulkan 1.3 features
|
|||
VkPhysicalDeviceVulkan13Features features{}; |
|||
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; |
|||
features.dynamicRendering = true; |
|||
features.synchronization2 = true; |
|||
|
|||
//vulkan 1.2 features
|
|||
VkPhysicalDeviceVulkan12Features features12{}; |
|||
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; |
|||
features12.bufferDeviceAddress = true; |
|||
features12.descriptorIndexing = true; |
|||
|
|||
|
|||
//use vkbootstrap to select a gpu.
|
|||
//We want a gpu that can write to the SDL surface and supports vulkan 1.3 with the correct features
|
|||
vkb::PhysicalDeviceSelector selector{ vkb_inst }; |
|||
vkb::PhysicalDevice physicalDevice = selector |
|||
.set_minimum_version(1, 3) |
|||
.set_required_features_13(features) |
|||
.set_required_features_12(features12) |
|||
.set_surface(_surface) |
|||
.select() |
|||
.value(); |
|||
|
|||
|
|||
//create the final vulkan device
|
|||
vkb::DeviceBuilder deviceBuilder{ physicalDevice }; |
|||
|
|||
vkb::Device vkbDevice = deviceBuilder.build().value(); |
|||
|
|||
// Get the VkDevice handle used in the rest of a vulkan application
|
|||
_device = vkbDevice.device; |
|||
_chosenGPU = physicalDevice.physical_device; |
|||
|
|||
_graphicsQueue = vkbDevice.get_queue(vkb::QueueType::graphics).value(); |
|||
_graphicsQueueFamily = vkbDevice.get_queue_index(vkb::QueueType::graphics).value(); |
|||
|
|||
// initialize the memory allocator
|
|||
VmaAllocatorCreateInfo allocatorInfo = {}; |
|||
allocatorInfo.physicalDevice = _chosenGPU; |
|||
allocatorInfo.device = _device; |
|||
allocatorInfo.instance = _instance; |
|||
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; |
|||
vmaCreateAllocator(&allocatorInfo, &_allocator); |
|||
|
|||
_mainDeletionQueue.push_function([&]() { |
|||
vmaDestroyAllocator(_allocator); |
|||
}); |
|||
|
|||
} |
|||
|
|||
void VkEngine::create_swapchain(uint32_t width, uint32_t height) |
|||
{ |
|||
vkb::SwapchainBuilder swapchainBuilder{ _chosenGPU,_device,_surface }; |
|||
|
|||
_swapchainImageFormat = VK_FORMAT_B8G8R8A8_UNORM; |
|||
|
|||
vkb::Swapchain vkbSwapchain = swapchainBuilder |
|||
//.use_default_format_selection()
|
|||
.set_desired_format(VkSurfaceFormatKHR{ .format = _swapchainImageFormat, .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }) |
|||
//use vsync present mode
|
|||
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR) |
|||
.set_desired_extent(width, height) |
|||
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT) |
|||
.build() |
|||
.value(); |
|||
|
|||
_swapchainExtent = vkbSwapchain.extent; |
|||
//store swapchain and its related images
|
|||
_swapchain = vkbSwapchain.swapchain; |
|||
_swapchainImages = vkbSwapchain.get_images().value(); |
|||
_swapchainImageViews = vkbSwapchain.get_image_views().value(); |
|||
} |
|||
|
|||
void VkEngine::destroy_swapchain() |
|||
{ |
|||
vkDestroySwapchainKHR(_device, _swapchain, nullptr); |
|||
|
|||
// destroy swapchain resources
|
|||
for (int i = 0; i < static_cast<int>(_swapchainImageViews.size()); i++) { |
|||
|
|||
vkDestroyImageView(_device, _swapchainImageViews[i], nullptr); |
|||
} |
|||
} |
|||
|
|||
void VkEngine::init_swapchain() |
|||
{ |
|||
create_swapchain(_windowExtent.width, _windowExtent.height); |
|||
|
|||
//draw image size will match the window
|
|||
VkExtent3D drawImageExtent = { |
|||
_windowExtent.width, |
|||
_windowExtent.height, |
|||
1 |
|||
}; |
|||
|
|||
//hardcoding the draw format to 32 bit float
|
|||
_drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT; |
|||
_drawImage.imageExtent = drawImageExtent; |
|||
|
|||
VkImageUsageFlags drawImageUsages{}; |
|||
drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
|||
drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
|||
drawImageUsages |= VK_IMAGE_USAGE_STORAGE_BIT; |
|||
drawImageUsages |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
|||
|
|||
VkImageCreateInfo rimg_info = vkinit::image_create_info(_drawImage.imageFormat, drawImageUsages, drawImageExtent); |
|||
|
|||
//for the draw image, we want to allocate it from gpu local memory
|
|||
VmaAllocationCreateInfo rimg_allocinfo = {}; |
|||
rimg_allocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; |
|||
rimg_allocinfo.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
|||
|
|||
//allocate and create the image
|
|||
vmaCreateImage(_allocator, &rimg_info, &rimg_allocinfo, &_drawImage.image, &_drawImage.allocation, nullptr); |
|||
|
|||
//build a image-view for the draw image to use for rendering
|
|||
VkImageViewCreateInfo rview_info = vkinit::imageview_create_info(_drawImage.imageFormat, _drawImage.image, VK_IMAGE_ASPECT_COLOR_BIT); |
|||
|
|||
VK_CHECK(vkCreateImageView(_device, &rview_info, nullptr, &_drawImage.imageView)); |
|||
|
|||
//add to deletion queues
|
|||
_mainDeletionQueue.push_function([=]() { |
|||
vkDestroyImageView(_device, _drawImage.imageView, nullptr); |
|||
vmaDestroyImage(_allocator, _drawImage.image, _drawImage.allocation); |
|||
}); |
|||
|
|||
} |
|||
|
|||
void VkEngine::init_commands() |
|||
{ |
|||
VkCommandPoolCreateInfo commandPoolInfo = vkinit::command_pool_create_info(_graphicsQueueFamily, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); |
|||
|
|||
for (int i = 0; i < static_cast<int>(FRAME_OVERLAP); i++) { |
|||
|
|||
VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_frames[i]._commandPool)); |
|||
|
|||
// allocate the default command buffer that we will use for rendering
|
|||
VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(_frames[i]._commandPool, 1); |
|||
|
|||
VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_frames[i]._mainCommandBuffer)); |
|||
} |
|||
} |
|||
|
|||
void VkEngine::init_sync_structures() |
|||
{ |
|||
//create syncronization structures
|
|||
//one fence to control when the gpu has finished rendering the frame,
|
|||
//and 2 semaphores to syncronize rendering with swapchain
|
|||
//we want the fence to start signalled so we can wait on it on the first frame
|
|||
VkFenceCreateInfo fenceCreateInfo = vkinit::fence_create_info(VK_FENCE_CREATE_SIGNALED_BIT); |
|||
VkSemaphoreCreateInfo semaphoreCreateInfo = vkinit::semaphore_create_info(); |
|||
|
|||
for (int i = 0; i < static_cast<int>(FRAME_OVERLAP); i++) { |
|||
VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &_frames[i]._renderFence)); |
|||
|
|||
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._swapchainSemaphore)); |
|||
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._renderSemaphore)); |
|||
} |
|||
} |
@ -0,0 +1,110 @@ |
|||
#ifndef VKENGINE_H |
|||
#define VKENGINE_H |
|||
|
|||
#pragma once |
|||
|
|||
#include <VkTypes.h> |
|||
|
|||
#include <QObject> |
|||
|
|||
struct DeletionQueue |
|||
{ |
|||
std::deque<std::function<void()>> deletors; |
|||
|
|||
void push_function(std::function<void()>&& function) { |
|||
deletors.push_back(function); |
|||
} |
|||
|
|||
void flush() { |
|||
// reverse iterate the deletion queue to execute all the functions
|
|||
for (auto it = deletors.rbegin(); it != deletors.rend(); it++) { |
|||
(*it)(); //call functors
|
|||
} |
|||
|
|||
deletors.clear(); |
|||
} |
|||
}; |
|||
|
|||
|
|||
struct FrameData { |
|||
|
|||
VkCommandPool _commandPool; |
|||
VkCommandBuffer _mainCommandBuffer; |
|||
|
|||
VkSemaphore _swapchainSemaphore, _renderSemaphore; |
|||
VkFence _renderFence; |
|||
|
|||
DeletionQueue _deletionQueue; |
|||
}; |
|||
|
|||
constexpr unsigned int FRAME_OVERLAP = 2; |
|||
|
|||
class VkEngine |
|||
{ |
|||
public: |
|||
VkEngine(); |
|||
|
|||
bool _isInitialized{ false }; |
|||
int _frameNumber {0}; |
|||
bool stop_rendering{ false }; |
|||
VkExtent2D _windowExtent{ 1700 , 900 }; |
|||
|
|||
struct SDL_Window* _window{ nullptr }; |
|||
|
|||
VkInstance _instance;// Vulkan library handle
|
|||
VkDebugUtilsMessengerEXT _debug_messenger;// Vulkan debug output handle
|
|||
VkPhysicalDevice _chosenGPU;// GPU chosen as the default device
|
|||
VkDevice _device; // Vulkan device for commands
|
|||
VkSurfaceKHR _surface;// Vulkan window surface
|
|||
|
|||
VkSwapchainKHR _swapchain; |
|||
VkFormat _swapchainImageFormat; |
|||
|
|||
std::vector<VkImage> _swapchainImages; |
|||
std::vector<VkImageView> _swapchainImageViews; |
|||
VkExtent2D _swapchainExtent; |
|||
|
|||
FrameData _frames[FRAME_OVERLAP]; |
|||
|
|||
FrameData& get_current_frame() |
|||
{ |
|||
return _frames[_frameNumber % FRAME_OVERLAP]; |
|||
} |
|||
|
|||
DeletionQueue _mainDeletionQueue; |
|||
|
|||
VkQueue _graphicsQueue; |
|||
uint32_t _graphicsQueueFamily; |
|||
|
|||
VmaAllocator _allocator; |
|||
|
|||
//draw resources
|
|||
AllocatedImage _drawImage; |
|||
VkExtent2D _drawExtent; |
|||
|
|||
static VkEngine& Get(); |
|||
|
|||
//initializes everything in the engine
|
|||
void init(); |
|||
|
|||
//shuts down the engine
|
|||
void cleanup(); |
|||
|
|||
//draw loop
|
|||
void draw(); |
|||
|
|||
//run main loop
|
|||
void run(); |
|||
|
|||
private: |
|||
|
|||
void init_vulkan(); |
|||
void init_swapchain(); |
|||
void init_commands(); |
|||
void init_sync_structures(); |
|||
|
|||
void create_swapchain(uint32_t width, uint32_t height); |
|||
void destroy_swapchain(); |
|||
}; |
|||
|
|||
#endif // VKENGINE_H
|
@ -0,0 +1,34 @@ |
|||
#include "VkImages.h" |
|||
#include "VkInitializers.h" |
|||
|
|||
void vkutil::transition_image(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout) |
|||
{ |
|||
VkImageMemoryBarrier2 imageBarrier {.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2}; |
|||
imageBarrier.pNext = nullptr; |
|||
|
|||
imageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; |
|||
imageBarrier.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT; |
|||
imageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; |
|||
imageBarrier.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT; |
|||
|
|||
imageBarrier.oldLayout = currentLayout; |
|||
imageBarrier.newLayout = newLayout; |
|||
|
|||
VkImageAspectFlags aspectMask = (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; |
|||
imageBarrier.subresourceRange = vkinit::image_subresource_range(aspectMask); |
|||
imageBarrier.image = image; |
|||
|
|||
VkDependencyInfo depInfo {}; |
|||
depInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; |
|||
depInfo.pNext = nullptr; |
|||
|
|||
depInfo.imageMemoryBarrierCount = 1; |
|||
depInfo.pImageMemoryBarriers = &imageBarrier; |
|||
|
|||
vkCmdPipelineBarrier2(cmd, &depInfo); |
|||
} |
|||
|
|||
//VkImages::VkImages()
|
|||
//{
|
|||
|
|||
//}
|
@ -0,0 +1,22 @@ |
|||
#ifndef VKIMAGES_H |
|||
#define VKIMAGES_H |
|||
|
|||
#include <QObject> |
|||
|
|||
#pragma once |
|||
|
|||
#include <vulkan/vulkan.h> |
|||
|
|||
namespace vkutil { |
|||
|
|||
void transition_image(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout); |
|||
} |
|||
|
|||
|
|||
//class VkImages
|
|||
//{
|
|||
//public:
|
|||
// VkImages();
|
|||
//};
|
|||
|
|||
#endif // VKIMAGES_H
|
@ -0,0 +1,342 @@ |
|||
#include "VkInitializers.h" |
|||
|
|||
//> init_cmd
|
|||
VkCommandPoolCreateInfo vkinit::command_pool_create_info(uint32_t queueFamilyIndex, |
|||
VkCommandPoolCreateFlags flags /*= 0*/) |
|||
{ |
|||
VkCommandPoolCreateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
info.queueFamilyIndex = queueFamilyIndex; |
|||
info.flags = flags; |
|||
return info; |
|||
} |
|||
|
|||
|
|||
VkCommandBufferAllocateInfo vkinit::command_buffer_allocate_info( |
|||
VkCommandPool pool, uint32_t count /*= 1*/) |
|||
{ |
|||
VkCommandBufferAllocateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
info.commandPool = pool; |
|||
info.commandBufferCount = count; |
|||
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; |
|||
return info; |
|||
} |
|||
//< init_cmd
|
|||
//
|
|||
//> init_cmd_draw
|
|||
VkCommandBufferBeginInfo vkinit::command_buffer_begin_info(VkCommandBufferUsageFlags flags /*= 0*/) |
|||
{ |
|||
VkCommandBufferBeginInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
info.pInheritanceInfo = nullptr; |
|||
info.flags = flags; |
|||
return info; |
|||
} |
|||
//< init_cmd_draw
|
|||
|
|||
//> init_sync
|
|||
VkFenceCreateInfo vkinit::fence_create_info(VkFenceCreateFlags flags /*= 0*/) |
|||
{ |
|||
VkFenceCreateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
info.flags = flags; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
VkSemaphoreCreateInfo vkinit::semaphore_create_info(VkSemaphoreCreateFlags flags /*= 0*/) |
|||
{ |
|||
VkSemaphoreCreateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
info.flags = flags; |
|||
return info; |
|||
} |
|||
//< init_sync
|
|||
|
|||
//> init_submit
|
|||
VkSemaphoreSubmitInfo vkinit::semaphore_submit_info(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore) |
|||
{ |
|||
VkSemaphoreSubmitInfo submitInfo{}; |
|||
submitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; |
|||
submitInfo.pNext = nullptr; |
|||
submitInfo.semaphore = semaphore; |
|||
submitInfo.stageMask = stageMask; |
|||
submitInfo.deviceIndex = 0; |
|||
submitInfo.value = 1; |
|||
|
|||
return submitInfo; |
|||
} |
|||
|
|||
VkCommandBufferSubmitInfo vkinit::command_buffer_submit_info(VkCommandBuffer cmd) |
|||
{ |
|||
VkCommandBufferSubmitInfo info{}; |
|||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; |
|||
info.pNext = nullptr; |
|||
info.commandBuffer = cmd; |
|||
info.deviceMask = 0; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
VkSubmitInfo2 vkinit::submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo* signalSemaphoreInfo, |
|||
VkSemaphoreSubmitInfo* waitSemaphoreInfo) |
|||
{ |
|||
VkSubmitInfo2 info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2; |
|||
info.pNext = nullptr; |
|||
|
|||
info.waitSemaphoreInfoCount = waitSemaphoreInfo == nullptr ? 0 : 1; |
|||
info.pWaitSemaphoreInfos = waitSemaphoreInfo; |
|||
|
|||
info.signalSemaphoreInfoCount = signalSemaphoreInfo == nullptr ? 0 : 1; |
|||
info.pSignalSemaphoreInfos = signalSemaphoreInfo; |
|||
|
|||
info.commandBufferInfoCount = 1; |
|||
info.pCommandBufferInfos = cmd; |
|||
|
|||
return info; |
|||
} |
|||
//< init_submit
|
|||
|
|||
VkPresentInfoKHR vkinit::present_info() |
|||
{ |
|||
VkPresentInfoKHR info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; |
|||
info.pNext = 0; |
|||
|
|||
info.swapchainCount = 0; |
|||
info.pSwapchains = nullptr; |
|||
info.pWaitSemaphores = nullptr; |
|||
info.waitSemaphoreCount = 0; |
|||
info.pImageIndices = nullptr; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
//> color_info
|
|||
VkRenderingAttachmentInfo vkinit::attachment_info( |
|||
VkImageView view, VkClearValue* clear ,VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/) |
|||
{ |
|||
VkRenderingAttachmentInfo colorAttachment {}; |
|||
colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; |
|||
colorAttachment.pNext = nullptr; |
|||
|
|||
colorAttachment.imageView = view; |
|||
colorAttachment.imageLayout = layout; |
|||
colorAttachment.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; |
|||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
|||
if (clear) { |
|||
colorAttachment.clearValue = *clear; |
|||
} |
|||
|
|||
return colorAttachment; |
|||
} |
|||
//< color_info
|
|||
//> depth_info
|
|||
VkRenderingAttachmentInfo vkinit::depth_attachment_info( |
|||
VkImageView view, VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/) |
|||
{ |
|||
VkRenderingAttachmentInfo depthAttachment {}; |
|||
depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; |
|||
depthAttachment.pNext = nullptr; |
|||
|
|||
depthAttachment.imageView = view; |
|||
depthAttachment.imageLayout = layout; |
|||
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
|||
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
|||
depthAttachment.clearValue.depthStencil.depth = 0.f; |
|||
|
|||
return depthAttachment; |
|||
} |
|||
//< depth_info
|
|||
//> render_info
|
|||
VkRenderingInfo vkinit::rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, |
|||
VkRenderingAttachmentInfo* depthAttachment) |
|||
{ |
|||
VkRenderingInfo renderInfo {}; |
|||
renderInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; |
|||
renderInfo.pNext = nullptr; |
|||
|
|||
renderInfo.renderArea = VkRect2D { VkOffset2D { 0, 0 }, renderExtent }; |
|||
renderInfo.layerCount = 1; |
|||
renderInfo.colorAttachmentCount = 1; |
|||
renderInfo.pColorAttachments = colorAttachment; |
|||
renderInfo.pDepthAttachment = depthAttachment; |
|||
renderInfo.pStencilAttachment = nullptr; |
|||
|
|||
return renderInfo; |
|||
} |
|||
//< render_info
|
|||
//> subresource
|
|||
VkImageSubresourceRange vkinit::image_subresource_range(VkImageAspectFlags aspectMask) |
|||
{ |
|||
VkImageSubresourceRange subImage {}; |
|||
subImage.aspectMask = aspectMask; |
|||
subImage.baseMipLevel = 0; |
|||
subImage.levelCount = VK_REMAINING_MIP_LEVELS; |
|||
subImage.baseArrayLayer = 0; |
|||
subImage.layerCount = VK_REMAINING_ARRAY_LAYERS; |
|||
|
|||
return subImage; |
|||
} |
|||
//< subresource
|
|||
|
|||
|
|||
|
|||
VkDescriptorSetLayoutBinding vkinit::descriptorset_layout_binding(VkDescriptorType type, VkShaderStageFlags stageFlags, |
|||
uint32_t binding) |
|||
{ |
|||
VkDescriptorSetLayoutBinding setbind = {}; |
|||
setbind.binding = binding; |
|||
setbind.descriptorCount = 1; |
|||
setbind.descriptorType = type; |
|||
setbind.pImmutableSamplers = nullptr; |
|||
setbind.stageFlags = stageFlags; |
|||
|
|||
return setbind; |
|||
} |
|||
|
|||
VkDescriptorSetLayoutCreateInfo vkinit::descriptorset_layout_create_info(VkDescriptorSetLayoutBinding* bindings, |
|||
uint32_t bindingCount) |
|||
{ |
|||
VkDescriptorSetLayoutCreateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
info.pBindings = bindings; |
|||
info.bindingCount = bindingCount; |
|||
info.flags = 0; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
VkWriteDescriptorSet vkinit::write_descriptor_image(VkDescriptorType type, VkDescriptorSet dstSet, |
|||
VkDescriptorImageInfo* imageInfo, uint32_t binding) |
|||
{ |
|||
VkWriteDescriptorSet write = {}; |
|||
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; |
|||
write.pNext = nullptr; |
|||
|
|||
write.dstBinding = binding; |
|||
write.dstSet = dstSet; |
|||
write.descriptorCount = 1; |
|||
write.descriptorType = type; |
|||
write.pImageInfo = imageInfo; |
|||
|
|||
return write; |
|||
} |
|||
|
|||
VkWriteDescriptorSet vkinit::write_descriptor_buffer(VkDescriptorType type, VkDescriptorSet dstSet, |
|||
VkDescriptorBufferInfo* bufferInfo, uint32_t binding) |
|||
{ |
|||
VkWriteDescriptorSet write = {}; |
|||
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; |
|||
write.pNext = nullptr; |
|||
|
|||
write.dstBinding = binding; |
|||
write.dstSet = dstSet; |
|||
write.descriptorCount = 1; |
|||
write.descriptorType = type; |
|||
write.pBufferInfo = bufferInfo; |
|||
|
|||
return write; |
|||
} |
|||
|
|||
VkDescriptorBufferInfo vkinit::buffer_info(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range) |
|||
{ |
|||
VkDescriptorBufferInfo binfo {}; |
|||
binfo.buffer = buffer; |
|||
binfo.offset = offset; |
|||
binfo.range = range; |
|||
return binfo; |
|||
} |
|||
|
|||
//> image_set
|
|||
VkImageCreateInfo vkinit::image_create_info(VkFormat format, VkImageUsageFlags usageFlags, VkExtent3D extent) |
|||
{ |
|||
VkImageCreateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
info.imageType = VK_IMAGE_TYPE_2D; |
|||
|
|||
info.format = format; |
|||
info.extent = extent; |
|||
|
|||
info.mipLevels = 1; |
|||
info.arrayLayers = 1; |
|||
|
|||
//for MSAA. we will not be using it by default, so default it to 1 sample per pixel.
|
|||
info.samples = VK_SAMPLE_COUNT_1_BIT; |
|||
|
|||
//optimal tiling, which means the image is stored on the best gpu format
|
|||
info.tiling = VK_IMAGE_TILING_OPTIMAL; |
|||
info.usage = usageFlags; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
VkImageViewCreateInfo vkinit::imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags) |
|||
{ |
|||
// build a image-view for the depth image to use for rendering
|
|||
VkImageViewCreateInfo info = {}; |
|||
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
info.viewType = VK_IMAGE_VIEW_TYPE_2D; |
|||
info.image = image; |
|||
info.format = format; |
|||
info.subresourceRange.baseMipLevel = 0; |
|||
info.subresourceRange.levelCount = 1; |
|||
info.subresourceRange.baseArrayLayer = 0; |
|||
info.subresourceRange.layerCount = 1; |
|||
info.subresourceRange.aspectMask = aspectFlags; |
|||
|
|||
return info; |
|||
} |
|||
//< image_set
|
|||
VkPipelineLayoutCreateInfo vkinit::pipeline_layout_create_info() |
|||
{ |
|||
VkPipelineLayoutCreateInfo info {}; |
|||
info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
// empty defaults
|
|||
info.flags = 0; |
|||
info.setLayoutCount = 0; |
|||
info.pSetLayouts = nullptr; |
|||
info.pushConstantRangeCount = 0; |
|||
info.pPushConstantRanges = nullptr; |
|||
return info; |
|||
} |
|||
|
|||
VkPipelineShaderStageCreateInfo vkinit::pipeline_shader_stage_create_info(VkShaderStageFlagBits stage, |
|||
VkShaderModule shaderModule, |
|||
const char * entry) |
|||
{ |
|||
VkPipelineShaderStageCreateInfo info {}; |
|||
info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |
|||
info.pNext = nullptr; |
|||
|
|||
// shader stage
|
|||
info.stage = stage; |
|||
// module containing the code for this shader stage
|
|||
info.module = shaderModule; |
|||
// the entry point of the shader
|
|||
info.pName = entry; |
|||
return info; |
|||
} |
|||
|
|||
//VkInitializers::VkInitializers()
|
|||
//{
|
|||
|
|||
//}
|
@ -0,0 +1,62 @@ |
|||
#ifndef VKINITIALIZERS_H |
|||
#define VKINITIALIZERS_H |
|||
|
|||
#include <QObject> |
|||
|
|||
#pragma once |
|||
|
|||
#include <VkTypes.h> |
|||
|
|||
namespace vkinit { |
|||
//> init_cmd
|
|||
VkCommandPoolCreateInfo command_pool_create_info(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags flags = 0); |
|||
VkCommandBufferAllocateInfo command_buffer_allocate_info(VkCommandPool pool, uint32_t count = 1); |
|||
//< init_cmd
|
|||
|
|||
VkCommandBufferBeginInfo command_buffer_begin_info(VkCommandBufferUsageFlags flags = 0); |
|||
VkCommandBufferSubmitInfo command_buffer_submit_info(VkCommandBuffer cmd); |
|||
|
|||
VkFenceCreateInfo fence_create_info(VkFenceCreateFlags flags = 0); |
|||
|
|||
VkSemaphoreCreateInfo semaphore_create_info(VkSemaphoreCreateFlags flags = 0); |
|||
|
|||
VkSubmitInfo2 submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo* signalSemaphoreInfo, |
|||
VkSemaphoreSubmitInfo* waitSemaphoreInfo); |
|||
VkPresentInfoKHR present_info(); |
|||
|
|||
VkRenderingAttachmentInfo attachment_info(VkImageView view, VkClearValue* clear, VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/); |
|||
|
|||
VkRenderingAttachmentInfo depth_attachment_info(VkImageView view, |
|||
VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/); |
|||
|
|||
VkRenderingInfo rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, |
|||
VkRenderingAttachmentInfo* depthAttachment); |
|||
|
|||
VkImageSubresourceRange image_subresource_range(VkImageAspectFlags aspectMask); |
|||
|
|||
VkSemaphoreSubmitInfo semaphore_submit_info(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore); |
|||
VkDescriptorSetLayoutBinding descriptorset_layout_binding(VkDescriptorType type, VkShaderStageFlags stageFlags, |
|||
uint32_t binding); |
|||
VkDescriptorSetLayoutCreateInfo descriptorset_layout_create_info(VkDescriptorSetLayoutBinding* bindings, |
|||
uint32_t bindingCount); |
|||
VkWriteDescriptorSet write_descriptor_image(VkDescriptorType type, VkDescriptorSet dstSet, |
|||
VkDescriptorImageInfo* imageInfo, uint32_t binding); |
|||
VkWriteDescriptorSet write_descriptor_buffer(VkDescriptorType type, VkDescriptorSet dstSet, |
|||
VkDescriptorBufferInfo* bufferInfo, uint32_t binding); |
|||
VkDescriptorBufferInfo buffer_info(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range); |
|||
|
|||
VkImageCreateInfo image_create_info(VkFormat format, VkImageUsageFlags usageFlags, VkExtent3D extent); |
|||
VkImageViewCreateInfo imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags); |
|||
VkPipelineLayoutCreateInfo pipeline_layout_create_info(); |
|||
VkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info(VkShaderStageFlagBits stage, |
|||
VkShaderModule shaderModule, |
|||
const char * entry = "main"); |
|||
} // namespace vkinit
|
|||
|
|||
//class VkInitializers
|
|||
//{
|
|||
//public:
|
|||
// VkInitializers();
|
|||
//};
|
|||
|
|||
#endif // VKINITIALIZERS_H
|
@ -0,0 +1,6 @@ |
|||
#include "VkLoader.h" |
|||
|
|||
VkLoader::VkLoader() |
|||
{ |
|||
|
|||
} |
@ -0,0 +1,12 @@ |
|||
#ifndef VKLOADER_H |
|||
#define VKLOADER_H |
|||
|
|||
#include <QObject> |
|||
|
|||
class VkLoader |
|||
{ |
|||
public: |
|||
VkLoader(); |
|||
}; |
|||
|
|||
#endif // VKLOADER_H
|
@ -0,0 +1,17 @@ |
|||
#include "VkMain.h" |
|||
|
|||
VkMain::VkMain() |
|||
{ |
|||
|
|||
} |
|||
|
|||
void VkMain::mainRun() |
|||
{ |
|||
VkEngine engine; |
|||
|
|||
engine.init(); |
|||
|
|||
engine.run(); |
|||
|
|||
engine.cleanup(); |
|||
} |
@ -0,0 +1,15 @@ |
|||
#ifndef VKMAIN_H |
|||
#define VKMAIN_H |
|||
|
|||
#include <VkEngine.h> |
|||
|
|||
#include <QObject> |
|||
|
|||
class VkMain |
|||
{ |
|||
public: |
|||
VkMain(); |
|||
void mainRun(); |
|||
}; |
|||
|
|||
#endif // VKMAIN_H
|
@ -0,0 +1,6 @@ |
|||
#include "VkPipelines.h" |
|||
|
|||
VkPipelines::VkPipelines() |
|||
{ |
|||
|
|||
} |
@ -0,0 +1,12 @@ |
|||
#ifndef VKPIPELINES_H |
|||
#define VKPIPELINES_H |
|||
|
|||
#include <QObject> |
|||
|
|||
class VkPipelines |
|||
{ |
|||
public: |
|||
VkPipelines(); |
|||
}; |
|||
|
|||
#endif // VKPIPELINES_H
|
@ -0,0 +1,41 @@ |
|||
#ifndef VKTYPES_H |
|||
#define VKTYPES_H |
|||
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <optional> |
|||
#include <string> |
|||
#include <vector> |
|||
#include <span> |
|||
#include <array> |
|||
#include <functional> |
|||
#include <deque> |
|||
|
|||
#include <vulkan.h> |
|||
#include <vk_enum_string_helper.h> |
|||
#include <vma/vk_mem_alloc.h> |
|||
|
|||
#include <fmt/core.h> |
|||
|
|||
#include <glm/mat4x4.hpp> |
|||
#include <glm/vec4.hpp> |
|||
|
|||
struct AllocatedImage { |
|||
VkImage image; |
|||
VkImageView imageView; |
|||
VmaAllocation allocation; |
|||
VkExtent3D imageExtent; |
|||
VkFormat imageFormat; |
|||
}; |
|||
|
|||
#define VK_CHECK(x) \ |
|||
do { \ |
|||
VkResult err = x; \ |
|||
if (err) { \ |
|||
fmt::print("Detected Vulkan error: {}", string_VkResult(err)); \ |
|||
abort(); \ |
|||
} \ |
|||
} while (0) |
|||
|
|||
#endif // VKTYPES_H
|
@ -0,0 +1,17 @@ |
|||
{ |
|||
"description": "This file is generated by qmake to be read by androiddeployqt and should not be modified by hand.", |
|||
"qt": "/opt/Qt5.13.2/5.13.2/android_arm64_v8a", |
|||
"sdk": "/home/ali-mehrabani/host-projects/Android/Sdk", |
|||
"sdkBuildToolsRevision": "30.0.0", |
|||
"ndk": "/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b", |
|||
"toolchain-prefix": "llvm", |
|||
"tool-prefix": "llvm", |
|||
"toolchain-version": "4.9", |
|||
"ndk-host": "linux-x86_64", |
|||
"target-architecture": "arm64-v8a", |
|||
"android-package-source-directory": "/home/ali-mehrabani/Qt_projects/VkTest/android", |
|||
"qml-root-path": "/home/ali-mehrabani/Qt_projects/VkTest", |
|||
"stdcpp-path": "/home/ali-mehrabani/host-projects/Android/Sdk/ndk/android-ndk-r20b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so", |
|||
"useLLVM": true, |
|||
"application-binary": "/home/ali-mehrabani/Qt_projects/VkTest/libVkTest.so" |
|||
} |
Loading…
Reference in new issue