Compare commits

...
Sign in to create a new pull request.

6 commits

10 changed files with 546 additions and 501 deletions

View file

@ -121,6 +121,7 @@ sources = [
'vk_images.cpp',
'vk_descriptors.cpp',
'vk_pipelines.cpp',
'vk_gui.cpp',
'main.cpp',
]

View file

@ -2,11 +2,11 @@
void DescriptorLayoutBuilder::add_binding(uint32_t binding, VkDescriptorType type)
{
VkDescriptorSetLayoutBinding newbind {};
newbind.binding = binding;
newbind.descriptorCount = 1;
newbind.descriptorType = type;
VkDescriptorSetLayoutBinding newbind{
.binding = binding,
.descriptorType = type,
.descriptorCount = 1,
};
bindings.push_back(newbind);
}
@ -25,18 +25,16 @@ VkDescriptorSetLayout DescriptorLayoutBuilder::build(VkDevice device,
b.stageFlags |= shaderStages;
}
VkDescriptorSetLayoutCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
VkDescriptorSetLayoutCreateInfo info{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = pNext,
.flags = flags,
.bindingCount = (uint32_t)bindings.size(),
.pBindings = bindings.data(),
};
info.pNext = pNext;
info.pBindings = bindings.data();
info.bindingCount = (uint32_t)bindings.size();
info.flags = flags;
VkDescriptorSetLayout set;
VK_CHECK(vkCreateDescriptorSetLayout(device,
&info, nullptr, &set));
VK_CHECK(vkCreateDescriptorSetLayout(device, &info, nullptr, &set));
return set;
}
@ -46,19 +44,19 @@ void DescriptorAllocator::init_pool(VkDevice device, uint32_t maxSets,
{
std::vector<VkDescriptorPoolSize> poolSizes;
for(PoolSizeRatio ratio : poolRatios) {
poolSizes.push_back(VkDescriptorPoolSize{
poolSizes.push_back({
.type = ratio.type,
.descriptorCount = uint32_t(ratio.ratio * maxSets)
});
}
VkDescriptorPoolCreateInfo pool_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO
VkDescriptorPoolCreateInfo pool_info{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = 0,
.maxSets = maxSets,
.poolSizeCount = (uint32_t)poolSizes.size(),
.pPoolSizes = poolSizes.data(),
};
pool_info.flags = 0;
pool_info.maxSets = maxSets;
pool_info.poolSizeCount = (uint32_t)poolSizes.size();
pool_info.pPoolSizes = poolSizes.data();
vkCreateDescriptorPool(device, &pool_info, nullptr, &pool);
}
@ -75,15 +73,13 @@ void DescriptorAllocator::destroy_pool(VkDevice device)
VkDescriptorSet DescriptorAllocator::allocate(VkDevice device, VkDescriptorSetLayout layout)
{
VkDescriptorSetAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO
VkDescriptorSetAllocateInfo allocInfo{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = pool,
.descriptorSetCount = 1,
.pSetLayouts = &layout,
};
allocInfo.pNext = nullptr;
allocInfo.descriptorPool = pool;
allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = &layout;
VkDescriptorSet ds;
VK_CHECK(vkAllocateDescriptorSets(device, &allocInfo, &ds));

View file

@ -3,18 +3,13 @@
#include "vk_pipelines.h"
#include <print>
#include <SDL.h>
#include <SDL_vulkan.h>
#include <vk_types.h>
#include <vk_initializers.h>
#include "VkBootstrap.h"
#include <chrono>
#include <thread>
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_vulkan.h"
#include <SDL_vulkan.h>
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"
@ -32,18 +27,7 @@ void VulkanEngine::init()
assert(loadedEngine == nullptr);
loadedEngine = this;
// We initialize SDL and create a window with it.
SDL_Init(SDL_INIT_VIDEO);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN);
_window = SDL_CreateWindow(
"Vulkan Engine",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
int(_windowExtent.width),
int(_windowExtent.height),
window_flags);
_window = _gui.init_window(_windowExtent);
init_vulkan();
init_swapchain();
@ -51,7 +35,7 @@ void VulkanEngine::init()
init_sync_structures();
init_descriptors();
init_pipelines();
init_imgui();
_gui.init_imgui(VulkanEngine::Get());
//everything went fine
_isInitialized = true;
@ -81,14 +65,14 @@ void VulkanEngine::cleanup()
vkDestroyDevice(_device, nullptr);
vkb::destroy_debug_utils_messenger(_instance, _debug_messenger);
vkDestroyInstance(_instance, nullptr);
SDL_DestroyWindow(_window);
_gui.destroy(_window);
}
loadedEngine = nullptr;
}
void VulkanEngine::draw()
{
Transaction VulkanEngine::begin_transaction() {
// ZED: begin command transaction
// 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();
@ -103,44 +87,24 @@ void VulkanEngine::draw()
VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
_drawExtent.width = _drawImage.imageExtent.width;
_drawExtent.height = _drawImage.imageExtent.height;
VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
// transition our main draw image into general layout so we can write into it
// we will overwrite it all so we dont care about what was the older layout
return {cmd, swapchainImageIndex};
}
vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
draw_background(cmd);
vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkutil::copy_image_to_image(cmd, _drawImage.image,
_swapchainImages[swapchainImageIndex],
_drawExtent, _swapchainExtent);
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
draw_imgui(cmd, _swapchainImageViews[swapchainImageIndex]);
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
VK_CHECK(vkEndCommandBuffer(cmd));
void VulkanEngine::commit_transaction(Transaction& t) {
VK_CHECK(vkEndCommandBuffer(t.cmd));
// ZED: submit command to queue
//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);
VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(t.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);
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
@ -150,16 +114,15 @@ void VulkanEngine::draw()
// 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;
VkPresentInfoKHR presentInfo{
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = nullptr,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &get_current_frame()._renderSemaphore,
.swapchainCount = 1,
.pSwapchains = &_swapchain,
.pImageIndices = &t.swapchainImageIndex,
};
VK_CHECK(vkQueuePresentKHR(_graphicsQueue, &presentInfo));
@ -167,70 +130,61 @@ void VulkanEngine::draw()
_frameNumber++;
}
void VulkanEngine::draw()
{
auto t = begin_transaction();
// ZED: draw the things
_drawExtent.width = _drawImage.imageExtent.width;
_drawExtent.height = _drawImage.imageExtent.height;
// transition our main draw image into general layout so we can write into it
// we will overwrite it all so we dont care about what was the older layout
vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
draw_background(t.cmd);
// ZED: ?
vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
// ZED: ?
vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex],
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkutil::copy_image_to_image(t.cmd, _drawImage.image,
_swapchainImages[t.swapchainImageIndex],
_drawExtent, _swapchainExtent);
// ZED: ?
vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
_gui.draw_imgui(_swapchainExtent, t.cmd, _swapchainImageViews[t.swapchainImageIndex]);
// ZED: end drawing the things
// ZED: finalize image and commit command buffer
vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
commit_transaction(t);
}
void VulkanEngine::run()
{
SDL_Event e;
bool bQuit = false;
bool stop_rendering = false;
//main loop
while(!bQuit)
while(!_gui.should_quit)
{
//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;
}
_gui.poll_event();
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;
}
}
ImGui_ImplSDL2_ProcessEvent(&e);
}
if(stop_rendering) {
if(_gui.stop_rendering) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
continue;
}
render_imgui();
_gui.render_imgui(backgroundEffects, &currentBackgroundEffect);
draw();
}
}
void VulkanEngine::render_imgui() {
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
if (ImGui::Begin("background")) {
ComputeEffect& selected = backgroundEffects[currentBackgroundEffect];
ImGui::Text("Selected effect: %s", selected.name);
ImGui::SliderInt("Effect Index", &currentBackgroundEffect,0, backgroundEffects.size() - 1);
ImGui::InputFloat4("data1",(float*)& selected.data.data1);
ImGui::InputFloat4("data2",(float*)& selected.data.data2);
ImGui::InputFloat4("data3",(float*)& selected.data.data3);
ImGui::InputFloat4("data4",(float*)& selected.data.data4);
}
ImGui::End();
ImGui::Render();
}
void VulkanEngine::init_vulkan() {
vkb::InstanceBuilder builder;
@ -251,17 +205,18 @@ void VulkanEngine::init_vulkan() {
SDL_Vulkan_CreateSurface(_window, _instance, &_surface);
//vulkan 1.3 features
VkPhysicalDeviceVulkan13Features features13{};
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
features13.dynamicRendering = true;
features13.synchronization2 = true;
VkPhysicalDeviceVulkan13Features features13{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
.synchronization2 = true,
.dynamicRendering = true,
};
//vulkan 1.2 features
VkPhysicalDeviceVulkan12Features features12{};
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features12.bufferDeviceAddress = true;
features12.descriptorIndexing = true;
VkPhysicalDeviceVulkan12Features features12{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.descriptorIndexing = true,
.bufferDeviceAddress = true,
};
// use vkbootstrap to select a gpu
// We want a gpu that can write to the SDL surface
@ -284,11 +239,13 @@ void VulkanEngine::init_vulkan() {
_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;
VmaAllocatorCreateInfo allocatorInfo{
.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT,
.physicalDevice = _chosenGPU,
.device = _device,
.instance = _instance,
};
vmaCreateAllocator(&allocatorInfo, &_allocator);
_mainDeletionQueue.push_function([&]() {
@ -339,17 +296,18 @@ void VulkanEngine::init_swapchain() {
_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;
VkImageUsageFlags drawImageUsages =
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_STORAGE_BIT
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
VkImageCreateInfo rimg_info = vkinit::image_create_info(_drawImage.imageFormat, drawImageUsages, drawImageExtent);
VmaAllocationCreateInfo rimg_allocinfo{};
rimg_allocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
rimg_allocinfo.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VmaAllocationCreateInfo rimg_allocinfo{
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT),
};
//allocate and create the image
vmaCreateImage(_allocator, &rimg_info, &rimg_allocinfo, &_drawImage.image, &_drawImage.allocation, nullptr);
@ -430,7 +388,7 @@ void VulkanEngine::init_descriptors() {
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }
};
globalDescriptorAllocator.init_pool(_device, 10, sizes);
_globalDescriptorAllocator.init_pool(_device, 10, sizes);
// make the descriptor set layout for our compute draw
{
@ -441,27 +399,27 @@ void VulkanEngine::init_descriptors() {
// other code
//allocate a descriptor set for our draw image
_drawImageDescriptors = globalDescriptorAllocator.allocate(_device,_drawImageDescriptorLayout);
_drawImageDescriptors = _globalDescriptorAllocator.allocate(_device,_drawImageDescriptorLayout);
VkDescriptorImageInfo imgInfo{};
imgInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
imgInfo.imageView = _drawImage.imageView;
VkDescriptorImageInfo imgInfo{
.imageView = _drawImage.imageView,
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
};
VkWriteDescriptorSet drawImageWrite = {};
drawImageWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
drawImageWrite.pNext = nullptr;
drawImageWrite.dstBinding = 0;
drawImageWrite.dstSet = _drawImageDescriptors;
drawImageWrite.descriptorCount = 1;
drawImageWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
drawImageWrite.pImageInfo = &imgInfo;
VkWriteDescriptorSet drawImageWrite{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = _drawImageDescriptors,
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &imgInfo,
};
vkUpdateDescriptorSets(_device, 1, &drawImageWrite, 0, nullptr),
//make sure both the descriptor allocator and the new layout get cleaned up properly
_mainDeletionQueue.push_function([&]() {
globalDescriptorAllocator.destroy_pool(_device);
_globalDescriptorAllocator.destroy_pool(_device);
vkDestroyDescriptorSetLayout(_device, _drawImageDescriptorLayout, nullptr);
});
@ -470,77 +428,81 @@ void VulkanEngine::init_descriptors() {
void VulkanEngine::init_pipelines()
{
init_background_pipelines();
init_shaders();
}
void VulkanEngine::load_shader(const char *file_name, const char *entry_point, ComputeEffect effect) {
VkShaderModule shader;
bool good = vkutil::load_shader_module(file_name, _device, &shader);
assert(good && "failed to load shader");
VkPipelineShaderStageCreateInfo stageinfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
.module = shader,
.pName = entry_point,
};
VkComputePipelineCreateInfo computePipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
.stage = stageinfo,
.layout = _gradientPipelineLayout,
};
effect.layout = _gradientPipelineLayout;
VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &effect.pipeline));
backgroundEffects.push_back(effect);
vkDestroyShaderModule(_device, shader, nullptr);
_mainDeletionQueue.push_function([=,this]() {
vkDestroyPipeline(_device, effect.pipeline, nullptr);
});
}
void VulkanEngine::init_background_pipelines()
{
VkPipelineLayoutCreateInfo computeLayout{};
computeLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
computeLayout.pNext = nullptr;
computeLayout.pSetLayouts = &_drawImageDescriptorLayout;
computeLayout.setLayoutCount = 1;
VkPushConstantRange pushConstant{
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.offset = 0,
.size = sizeof(ComputePushConstants),
};
VkPushConstantRange pushConstant{};
pushConstant.offset = 0;
pushConstant.size = sizeof(ComputePushConstants) ;
pushConstant.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
computeLayout.pPushConstantRanges = &pushConstant;
computeLayout.pushConstantRangeCount = 1;
VkPipelineLayoutCreateInfo computeLayout{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1,
.pSetLayouts = &_drawImageDescriptorLayout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstant,
};
VK_CHECK(vkCreatePipelineLayout(_device, &computeLayout, nullptr, &_gradientPipelineLayout));
VkShaderModule gradientShader;
bool good = vkutil::load_shader_module("gradient_color.comp.spv", _device, &gradientShader);
assert(good && "failed to load gradient_color.comp.spv");
VkShaderModule skyShader;
good = vkutil::load_shader_module("sky.comp.spv", _device, &skyShader);
VkPipelineShaderStageCreateInfo stageinfo{};
stageinfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stageinfo.pNext = nullptr;
stageinfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
stageinfo.module = gradientShader;
stageinfo.pName = "main";
VkComputePipelineCreateInfo computePipelineCreateInfo{};
computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
computePipelineCreateInfo.pNext = nullptr;
computePipelineCreateInfo.layout = _gradientPipelineLayout;
computePipelineCreateInfo.stage = stageinfo;
ComputeEffect gradient;
gradient.layout = _gradientPipelineLayout;
gradient.name = "gradient";
gradient.data = {};
gradient.data.data1 = glm::vec4(1, 0, 0, 1);
gradient.data.data2 = glm::vec4(0, 0, 1, 1);
VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &gradient.pipeline));
// change the shader module only to create the sky
computePipelineCreateInfo.stage.module = skyShader;
ComputeEffect sky;
sky.layout = _gradientPipelineLayout;
sky.name = "sky";
sky.data = {};
// default sky
sky.data.data1 = glm::vec4(0.1, 0.2, 0.4, 0.97);
VK_CHECK(vkCreateComputePipelines(_device, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &sky.pipeline));
backgroundEffects.push_back(gradient);
backgroundEffects.push_back(sky);
vkDestroyShaderModule(_device, gradientShader, nullptr);
vkDestroyShaderModule(_device, skyShader, nullptr);
// final cleanup
_mainDeletionQueue.push_function([=,this]() {
vkDestroyPipelineLayout(_device, _gradientPipelineLayout, nullptr);
vkDestroyPipeline(_device, sky.pipeline, nullptr);
vkDestroyPipeline(_device, sky.pipeline, nullptr);
});
}
void VulkanEngine::init_shaders() {
/// gradient shader
load_shader("gradient_color.comp.spv", "main", {
.name="gradient",
.data={
.data1 = glm::vec4(1, 0, 0, 1),
.data2 = glm::vec4(0, 0, 1, 1),
}
});
load_shader("sky.comp.spv", "main", {
.name="sky",
.data = {
.data1 = glm::vec4(0.1, 0.2, 0.4, 0.97)
}
});
}
@ -565,75 +527,7 @@ void VulkanEngine::immediate_submit(std::function<void(VkCommandBuffer cmd)>&& f
VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, _immFence));
VK_CHECK(vkWaitForFences(_device, 1, &_immFence, true,9999999999));
}
void VulkanEngine::init_imgui()
{
// 1: create descriptor pool for IMGUI
// the size of the pool is very oversize, but it's copied from imgui demo
// itself.
VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } };
VkDescriptorPoolCreateInfo pool_info{};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1000;
pool_info.poolSizeCount = (uint32_t)std::size(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
VkDescriptorPool imguiPool;
VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool));
// 2: initialize the imgui library
ImGui::CreateContext();
ImGui_ImplSDL2_InitForVulkan(_window);
ImGui_ImplVulkan_InitInfo init_info{};
init_info.Instance = _instance;
init_info.PhysicalDevice = _chosenGPU;
init_info.Device = _device;
init_info.Queue = _graphicsQueue;
init_info.DescriptorPool = imguiPool;
init_info.MinImageCount = 3;
init_info.ImageCount = 3;
init_info.UseDynamicRendering = true;
init_info.PipelineRenderingCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
init_info.PipelineRenderingCreateInfo.colorAttachmentCount = 1;
init_info.PipelineRenderingCreateInfo.pColorAttachmentFormats = &_swapchainImageFormat;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
ImGui_ImplVulkan_Init(&init_info);
ImGui_ImplVulkan_CreateFontsTexture();
_mainDeletionQueue.push_function([=,this]() {
ImGui_ImplVulkan_Shutdown();
vkDestroyDescriptorPool(_device, imguiPool, nullptr);
});
}
void VulkanEngine::draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView)
{
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingInfo renderInfo = vkinit::rendering_info(_swapchainExtent, &colorAttachment, nullptr);
vkCmdBeginRendering(cmd, &renderInfo);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd);
vkCmdEndRendering(cmd);
}

View file

@ -5,23 +5,13 @@
#include <vk_types.h>
#include <vk_descriptors.h>
#include "vk_gui.h"
struct ComputePushConstants {
glm::vec4 data1;
glm::vec4 data2;
glm::vec4 data3;
glm::vec4 data4;
struct Transaction {
VkCommandBuffer cmd;
uint32_t swapchainImageIndex = 0;
};
struct ComputeEffect {
const char *name;
VkPipeline pipeline;
VkPipelineLayout layout;
ComputePushConstants data;
};
struct DeletionQueue {
std::deque<std::function<void()>> deletors;
@ -48,7 +38,6 @@ struct FrameData {
DeletionQueue _deletionQueue;
};
constexpr unsigned int FRAME_OVERLAP=2;
class VulkanEngine {
public:
@ -58,7 +47,7 @@ public:
VkPipeline _gradientPipeline;
VkPipelineLayout _gradientPipelineLayout;
DescriptorAllocator globalDescriptorAllocator;
DescriptorAllocator _globalDescriptorAllocator;
VkDescriptorSet _drawImageDescriptors;
VkDescriptorSetLayout _drawImageDescriptorLayout;
@ -105,6 +94,9 @@ public:
std::vector<ComputeEffect> backgroundEffects;
int currentBackgroundEffect{0};
// ZED's REFACTOR
VkGUI _gui;
static VulkanEngine& Get();
//initializes everything in the engine
@ -121,6 +113,9 @@ public:
void immediate_submit(std::function<void(VkCommandBuffer cmd)>&& function);
Transaction begin_transaction();
void commit_transaction(Transaction& cmd);
private:
void init_vulkan();
void init_swapchain();
@ -129,11 +124,10 @@ private:
void init_descriptors();
void init_pipelines();
void init_background_pipelines();
void init_imgui();
void init_shaders();
void load_shader(const char *file_name, const char *entry_point, ComputeEffect data);
void create_swapchain(uint32_t width, uint32_t height);
void destroy_swapchain();
void draw_background(VkCommandBuffer cmd);
void draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView);
void render_imgui();
};

151
vk_gui.cpp Normal file
View file

@ -0,0 +1,151 @@
#include "vk_gui.h"
#include "vk_initializers.h"
#include <SDL.h>
#include <SDL_vulkan.h>
#include <imgui.h>
#include <imgui_impl_sdl2.h>
#include <imgui_impl_vulkan.h>
#include "vk_engine.h"
struct SDL_Window* VkGUI::init_window(VkExtent2D windowExtent)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN);
return SDL_CreateWindow(
"Vulkan Engine",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
int(windowExtent.width),
int(windowExtent.height),
window_flags);
}
void VkGUI::init_imgui(VulkanEngine& engine)
{
// 1. create descriptor pool for IMGUI
// the size of the pool is very oversize, but it's copied from imgui demo
// itself.
VkDescriptorPoolSize pool_sizes[] = {
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
};
VkDescriptorPoolCreateInfo pool_info{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
.maxSets = 1000,
.poolSizeCount = (uint32_t)std::size(pool_sizes),
.pPoolSizes = pool_sizes,
};
VkDescriptorPool imguiPool;
VK_CHECK(vkCreateDescriptorPool(engine._device, &pool_info, nullptr, &imguiPool));
// 2: initialize the imgui library
ImGui::CreateContext();
ImGui_ImplSDL2_InitForVulkan(engine._window);
ImGui_ImplVulkan_InitInfo init_info{
.Instance = engine._instance,
.PhysicalDevice = engine._chosenGPU,
.Device = engine._device,
.Queue = engine._graphicsQueue,
.DescriptorPool = imguiPool,
.MinImageCount = 3,
.ImageCount = 3,
.MSAASamples = VK_SAMPLE_COUNT_1_BIT,
.UseDynamicRendering = true,
.PipelineRenderingCreateInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &engine._swapchainImageFormat,
},
};
ImGui_ImplVulkan_Init(&init_info);
ImGui_ImplVulkan_CreateFontsTexture();
engine._mainDeletionQueue.push_function([=,this]() {
ImGui_ImplVulkan_Shutdown();
vkDestroyDescriptorPool(engine._device, imguiPool, nullptr);
});
}
void VkGUI::draw_imgui(VkExtent2D& swapchainExtent, VkCommandBuffer cmd, VkImageView targetImageView)
{
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingInfo renderInfo = vkinit::rendering_info(swapchainExtent, &colorAttachment, nullptr);
vkCmdBeginRendering(cmd, &renderInfo);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd);
vkCmdEndRendering(cmd);
}
void VkGUI::render_imgui(std::vector<ComputeEffect>& backgroundEffects, int* currentBackgroundEffect)
{
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
if (ImGui::Begin("background")) {
ComputeEffect& selected = backgroundEffects[*currentBackgroundEffect];
ImGui::Text("Selected effect: %s", selected.name);
ImGui::SliderInt("Effect Index", currentBackgroundEffect,0, backgroundEffects.size() - 1);
ImGui::InputFloat4("data1",(float*)& selected.data.data1);
ImGui::InputFloat4("data2",(float*)& selected.data.data2);
ImGui::InputFloat4("data3",(float*)& selected.data.data3);
ImGui::InputFloat4("data4",(float*)& selected.data.data4);
}
ImGui::End();
ImGui::Render();
}
void VkGUI::destroy(struct SDL_Window* _window)
{
SDL_DestroyWindow(_window);
}
void VkGUI::poll_event() {
SDL_Event event;
while(SDL_PollEvent(&event) != 0) {
//close the window when user alt-f4s or clicks the X button
if(event.type == SDL_QUIT) {
should_quit = true;
}
if(event.type == SDL_WINDOWEVENT) {
if(event.window.event == SDL_WINDOWEVENT_MINIMIZED) {
stop_rendering = true;
}
if(event.window.event == SDL_WINDOWEVENT_RESTORED) {
stop_rendering = false;
}
}
ImGui_ImplSDL2_ProcessEvent(&event);
}
}

18
vk_gui.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include "vk_types.h"
class VulkanEngine;
class VkGUI {
public:
bool should_quit = false;
bool stop_rendering = false;
struct SDL_Window* init_window(VkExtent2D windowExtent);
void init_imgui(VulkanEngine& engine);
void draw_imgui(VkExtent2D& swapchainExtent, VkCommandBuffer cmd, VkImageView targetImageView);
void render_imgui(std::vector<ComputeEffect>& backgroundEffects, int* currentBackgroundEffect);
void destroy(struct SDL_Window* _window);
void poll_event();
};

View file

@ -3,28 +3,25 @@
void vkutil::transition_image(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout)
{
VkImageMemoryBarrier2 imageBarrier{};
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;
VkImageMemoryBarrier2 imageBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT,
.oldLayout = currentLayout,
.newLayout = newLayout,
.image = image,
.subresourceRange = vkinit::image_subresource_range(aspectMask),
};
VkDependencyInfo depInfo{
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &imageBarrier,
};
vkCmdPipelineBarrier2(cmd, &depInfo);
}
@ -33,39 +30,45 @@ void vkutil::copy_image_to_image(VkCommandBuffer cmd, VkImage source, VkImage de
{
VkImageBlit2 blitRegion{
.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
.pNext = nullptr
};
blitRegion.srcOffsets[1].x = srcSize.width;
blitRegion.srcOffsets[1].y = srcSize.height;
blitRegion.srcOffsets[1].z = 1;
blitRegion.srcSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
};
blitRegion.dstOffsets[1].x = dstSize.width;
blitRegion.dstOffsets[1].y = dstSize.height;
blitRegion.dstOffsets[1].z = 1;
blitRegion.dstSubresource = {
.aspectMask=VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel=0,
.baseArrayLayer=0,
.layerCount=1,
};
blitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blitRegion.srcSubresource.baseArrayLayer = 0;
blitRegion.srcSubresource.layerCount = 1;
blitRegion.srcSubresource.mipLevel = 0;
blitRegion.srcOffsets[1] = {
.x = int32_t(srcSize.width),
.y = int32_t(srcSize.height),
.z = 1,
};
blitRegion.dstSubresource.aspectMask=VK_IMAGE_ASPECT_COLOR_BIT;
blitRegion.dstSubresource.baseArrayLayer=0;
blitRegion.dstSubresource.layerCount=1;
blitRegion.dstSubresource.mipLevel=0;
blitRegion.dstOffsets[1] = {
.x = int32_t(dstSize.width),
.y = int32_t(dstSize.height),
.z = 1,
};
VkBlitImageInfo2 blitInfo{
.sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, .pNext = nullptr
.sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
.srcImage = source,
.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.dstImage = destination,
.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.regionCount = 1,
.pRegions = &blitRegion,
.filter = VK_FILTER_LINEAR,
};
blitInfo.dstImage = destination;
blitInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
blitInfo.srcImage = source;
blitInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
blitInfo.filter = VK_FILTER_LINEAR;
blitInfo.regionCount = 1;
blitInfo.pRegions = &blitRegion;
vkCmdBlitImage2(cmd, &blitInfo);
}

View file

@ -3,163 +3,137 @@
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;
return {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = flags,
.queueFamilyIndex = queueFamilyIndex,
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = count,
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = flags
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.flags = flags,
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = flags,
.pInheritanceInfo = nullptr,
};
}
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;
return {
.aspectMask = aspectMask,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.semaphore = semaphore,
.value = 1,
.stageMask = stageMask,
.deviceIndex = 0,
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.commandBuffer = cmd,
.deviceMask = 0,
};
}
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;
return {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.waitSemaphoreInfoCount = (waitSemaphoreInfo == nullptr ? 0u : 1u),
.pWaitSemaphoreInfos = waitSemaphoreInfo,
.commandBufferInfoCount = 1,
.pCommandBufferInfos = cmd,
.signalSemaphoreInfoCount = (signalSemaphoreInfo == nullptr ? 0u : 1u),
.pSignalSemaphoreInfos = signalSemaphoreInfo,
};
}
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;
info.samples = VK_SAMPLE_COUNT_1_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.usage = usageFlags;
return info;
return {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = format,
.extent = extent,
.mipLevels = 1,
.arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = usageFlags,
};
}
VkImageViewCreateInfo vkinit::imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags)
{
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;
return {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = format,
.subresourceRange = {
.aspectMask = aspectFlags,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
}
};
}
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;
VkRenderingAttachmentInfo colorAttachment{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = view,
.imageLayout = layout,
.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
if (clear) {
colorAttachment.clearValue = *clear;
@ -172,16 +146,13 @@ VkRenderingAttachmentInfo vkinit::attachment_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;
return {
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = VkRect2D { VkOffset2D { 0, 0 }, renderExtent },
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = colorAttachment,
.pDepthAttachment = depthAttachment,
.pStencilAttachment = nullptr,
};
}

View file

@ -23,13 +23,13 @@ bool vkutil::load_shader_module(const char* filePath,
file.close();
VkShaderModuleCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.pNext = nullptr;
VkShaderModuleCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.pNext = nullptr,
// codeSize has to be in bytes
createInfo.codeSize = buffer.size() * sizeof(uint32_t);
createInfo.pCode = buffer.data();
.codeSize = buffer.size() * sizeof(uint32_t),
.pCode = buffer.data(),
};
VkShaderModule shaderModule;
if(vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {

View file

@ -37,3 +37,20 @@ struct AllocatedImage {
VkExtent3D imageExtent;
VkFormat imageFormat;
};
struct ComputePushConstants {
glm::vec4 data1;
glm::vec4 data2;
glm::vec4 data3;
glm::vec4 data4;
};
struct ComputeEffect {
const char *name;
VkPipeline pipeline;
VkPipelineLayout layout;
ComputePushConstants data;
};
constexpr unsigned int FRAME_OVERLAP=2;