Compare commits
13 commits
master
...
refactor_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbda70e3a0 | ||
|
|
85d792e257 | ||
|
|
0e6d452580 | ||
|
|
6d29fb718b | ||
|
|
c905ef9ca7 | ||
|
|
5435880d34 | ||
|
|
10fc100e2b | ||
|
|
3d36517b4f | ||
|
|
b5c6774412 | ||
|
|
61931083c6 | ||
|
|
35198bce6b | ||
|
|
4f7ab6db68 | ||
|
|
d1d57ab682 |
29 changed files with 1379 additions and 564 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -29,3 +29,5 @@ backup
|
|||
coverage
|
||||
coverage/*
|
||||
.venv
|
||||
*.glb
|
||||
imgui.ini
|
||||
|
|
|
|||
12
Makefile
12
Makefile
|
|
@ -13,6 +13,9 @@ shaders:
|
|||
glslangValidator -V gradient.comp -o gradient.comp.spv
|
||||
glslangValidator -V sky.comp -o sky.comp.spv
|
||||
glslangValidator -V gradient_color.comp -o gradient_color.comp.spv
|
||||
glslangValidator -V colored_triangle.frag -o colored_triangle.frag.spv
|
||||
glslangValidator -V colored_triangle.vert -o colored_triangle.vert.spv
|
||||
glslangValidator -V colored_triangle_mesh.vert -o colored_triangle_mesh.vert.spv
|
||||
|
||||
%.cpp : %.rl
|
||||
ragel -I $(ROOT_DIR) -G1 -o $@ $<
|
||||
|
|
@ -23,9 +26,15 @@ shaders:
|
|||
%.png: %.dot
|
||||
dot -Tpng $< -o $@
|
||||
|
||||
%.glb: %.glb.gz
|
||||
gunzip -k $<
|
||||
|
||||
build:
|
||||
meson compile -j 10 -C $(ROOT_DIR)/builddir
|
||||
|
||||
meshes: basicmesh.glb
|
||||
@echo "Meshes made"
|
||||
|
||||
release_build:
|
||||
meson --wipe builddir -Db_ndebug=true --buildtype release
|
||||
meson compile -j 10 -C builddir
|
||||
|
|
@ -50,9 +59,10 @@ debug_run: build
|
|||
|
||||
clean:
|
||||
meson compile --clean -C builddir
|
||||
rm -f basicmesh.glb
|
||||
|
||||
debug_test: build
|
||||
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests -e "[pathing]"
|
||||
|
||||
money:
|
||||
scc --exclude-dir subprojects
|
||||
scc --exclude-dir subprojects,vendor
|
||||
|
|
|
|||
BIN
basicmesh.glb.gz
Normal file
BIN
basicmesh.glb.gz
Normal file
Binary file not shown.
13
colored_triangle.frag
Normal file
13
colored_triangle.frag
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#version 450
|
||||
|
||||
//shader input
|
||||
layout (location = 0) in vec3 inColor;
|
||||
|
||||
//output write
|
||||
layout (location = 0) out vec4 outFragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
//return red
|
||||
outFragColor = vec4(inColor,1.0f);
|
||||
}
|
||||
BIN
colored_triangle.frag.spv
Normal file
BIN
colored_triangle.frag.spv
Normal file
Binary file not shown.
24
colored_triangle.vert
Normal file
24
colored_triangle.vert
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
|
||||
layout (location = 0) out vec3 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
//const array of positions for the triangle
|
||||
const vec3 positions[3] = vec3[3](
|
||||
vec3(1.f,1.f, 0.0f),
|
||||
vec3(-1.f,1.f, 0.0f),
|
||||
vec3(0.f,-1.f, 0.0f)
|
||||
);
|
||||
|
||||
//const array of colors for the triangle
|
||||
const vec3 colors[3] = vec3[3](
|
||||
vec3(1.0f, 0.0f, 0.0f), //red
|
||||
vec3(0.0f, 1.0f, 0.0f), //green
|
||||
vec3(00.f, 0.0f, 1.0f) //blue
|
||||
);
|
||||
|
||||
//output the position of each vertex
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 1.0f);
|
||||
outColor = colors[gl_VertexIndex];
|
||||
}
|
||||
BIN
colored_triangle.vert.spv
Normal file
BIN
colored_triangle.vert.spv
Normal file
Binary file not shown.
37
colored_triangle_mesh.vert
Normal file
37
colored_triangle_mesh.vert
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#version 450
|
||||
#extension GL_EXT_buffer_reference : require
|
||||
|
||||
layout (location = 0) out vec3 outColor;
|
||||
layout (location = 1) out vec2 outUV;
|
||||
|
||||
struct Vertex {
|
||||
|
||||
vec3 position;
|
||||
float uv_x;
|
||||
vec3 normal;
|
||||
float uv_y;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(buffer_reference, std430) readonly buffer VertexBuffer{
|
||||
Vertex vertices[];
|
||||
};
|
||||
|
||||
//push constants block
|
||||
layout( push_constant ) uniform constants
|
||||
{
|
||||
mat4 render_matrix;
|
||||
VertexBuffer vertexBuffer;
|
||||
} PushConstants;
|
||||
|
||||
void main()
|
||||
{
|
||||
//load vertex data from device adress
|
||||
Vertex v = PushConstants.vertexBuffer.vertices[gl_VertexIndex];
|
||||
|
||||
//output data
|
||||
gl_Position = PushConstants.render_matrix *vec4(v.position, 1.0f);
|
||||
outColor = v.color.xyz;
|
||||
outUV.x = v.uv_x;
|
||||
outUV.y = v.uv_y;
|
||||
}
|
||||
BIN
colored_triangle_mesh.vert.spv
Normal file
BIN
colored_triangle_mesh.vert.spv
Normal file
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
|||
#pragma once
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <optional>
|
||||
|
||||
#define ENROLL_COMPONENT(COMPONENT, ...) \
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \
|
||||
template <> struct NameOf<COMPONENT> { \
|
||||
static constexpr const char *name = #COMPONENT; \
|
||||
};
|
||||
|
||||
// partial specialization (full specialization works too)
|
||||
namespace nlohmann {
|
||||
template <typename T>
|
||||
struct adl_serializer<std::optional<T>> {
|
||||
static void to_json(json& j, const std::optional<T>& opt) {
|
||||
if (opt == std::nullopt) {
|
||||
j = nullptr;
|
||||
} else {
|
||||
j = *opt; // this will call adl_serializer<T>::to_json which will
|
||||
// find the free function to_json in T's namespace!
|
||||
}
|
||||
}
|
||||
|
||||
static void from_json(const json& j, std::optional<T>& opt) {
|
||||
if (j.is_null() || j == false) {
|
||||
opt = std::nullopt;
|
||||
} else {
|
||||
opt = std::make_optional<T>(j.template get<T>());
|
||||
// same as above, but with adl_serializer<T>::from_json
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
17
meson.build
17
meson.build
|
|
@ -69,7 +69,6 @@ elif build_machine.system() == 'darwin'
|
|||
endif
|
||||
|
||||
vma = subproject('vulkan-memory-allocator').get_variable('vma_allocator_dep')
|
||||
# vulkan_headers = subproject('vulkan-headers').get_variable('vulkan_headers_dep')
|
||||
|
||||
imgui = subproject('imgui',
|
||||
default_options: {
|
||||
|
|
@ -80,6 +79,13 @@ imgui = subproject('imgui',
|
|||
|
||||
sdl2 = subproject('sdl2').get_variable('sdl2_dep')
|
||||
|
||||
fastgltf_opts = cmake.subproject_options()
|
||||
fastgltf_opts.add_cmake_defines({
|
||||
'FASTGLTF_DOWNLOAD_SIMDJSON': false,
|
||||
})
|
||||
|
||||
fastgltf_proj = cmake.subproject('fastgltf', options: fastgltf_opts)
|
||||
fastgltf = fastgltf_proj.get_variable('fastgltf_dep')
|
||||
|
||||
glm_opts = cmake.subproject_options()
|
||||
glm_opts.add_cmake_defines({
|
||||
|
|
@ -104,7 +110,6 @@ else
|
|||
})
|
||||
endif
|
||||
|
||||
json = subproject('nlohmann_json').get_variable('nlohmann_json_dep')
|
||||
vkbootstrap_proj = cmake.subproject('vk-bootstrap', options: vk_opts)
|
||||
vkbootstrap = vkbootstrap_proj.get_variable('vk_bootstrap_dep')
|
||||
|
||||
|
|
@ -114,7 +119,7 @@ dependencies += [
|
|||
glm,
|
||||
imgui,
|
||||
sdl2,
|
||||
json,
|
||||
fastgltf,
|
||||
]
|
||||
|
||||
sources = [
|
||||
|
|
@ -123,15 +128,21 @@ sources = [
|
|||
'vk_images.cpp',
|
||||
'vk_descriptors.cpp',
|
||||
'vk_pipelines.cpp',
|
||||
'vk_loader.cpp',
|
||||
'vk_gui.cpp',
|
||||
'main.cpp',
|
||||
]
|
||||
|
||||
# have to force this here for...cmake reasons
|
||||
include_dirs = include_directories('subprojects/fastgltf/include')
|
||||
|
||||
tests = [
|
||||
]
|
||||
|
||||
executable('hellovulk', sources,
|
||||
cpp_args: cpp_args,
|
||||
link_args: link_args,
|
||||
include_directories: include_dirs,
|
||||
win_subsystem: 'windows',
|
||||
override_options: exe_defaults,
|
||||
dependencies: dependencies)
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
#include "vk_types.h"
|
||||
#include "json_mods.hpp"
|
||||
|
||||
template <typename T> struct NameOf;
|
||||
|
||||
ENROLL_COMPONENT(VkSemaphoreCreateInfo, sType);
|
||||
ENROLL_COMPONENT(VkFenceCreateInfo, sType);
|
||||
ENROLL_COMPONENT(VkImageViewCreateInfo, sType, viewType, subresourceRange.baseMipLevel, subresourceRange.levelCount, subresourceRange.baseArrayLayer, subresourceRange.layerCount);
|
||||
0
stb_image.h → vendor/stb_image.h
vendored
0
stb_image.h → vendor/stb_image.h
vendored
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
713
vk_engine.cpp
713
vk_engine.cpp
|
|
@ -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,8 @@ void VulkanEngine::init()
|
|||
init_sync_structures();
|
||||
init_descriptors();
|
||||
init_pipelines();
|
||||
init_imgui();
|
||||
_gui.init_imgui(VulkanEngine::Get());
|
||||
init_default_data();
|
||||
|
||||
//everything went fine
|
||||
_isInitialized = true;
|
||||
|
|
@ -81,14 +66,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 +88,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 +115,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 +131,135 @@ 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);
|
||||
|
||||
vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
draw_geometry(t.cmd);
|
||||
|
||||
// ZED: ?
|
||||
vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
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);
|
||||
|
||||
// ZED: end drawing the things
|
||||
_gui.draw_imgui(_swapchainExtent, t.cmd, _swapchainImageViews[t.swapchainImageIndex]);
|
||||
|
||||
// ZED: finalize image and commit command buffer
|
||||
vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
commit_transaction(t);
|
||||
}
|
||||
|
||||
void VulkanEngine::draw_geometry(VkCommandBuffer cmd)
|
||||
{
|
||||
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(_drawImage.imageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
VkRenderingInfo renderInfo = vkinit::rendering_info(_drawExtent, &colorAttachment, nullptr);
|
||||
vkCmdBeginRendering(cmd, &renderInfo);
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _trianglePipeline);
|
||||
|
||||
VkViewport viewport{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = (float)_drawExtent.width,
|
||||
.height = (float)_drawExtent.height,
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
vkCmdSetViewport(cmd, 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor{
|
||||
.offset = { .x = 0, .y = 0, },
|
||||
.extent = _drawExtent
|
||||
};
|
||||
|
||||
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
||||
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
// draw rectangle
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _meshPipeline);
|
||||
|
||||
GPUDrawPushConstants push_constants{
|
||||
.worldMatrix = glm::mat4{ 1.0f },
|
||||
.vertexBuffer = rectangle.vertexBufferAddress,
|
||||
};
|
||||
|
||||
vkCmdPushConstants(cmd, _meshPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(GPUDrawPushConstants),
|
||||
&push_constants);
|
||||
vkCmdBindIndexBuffer(cmd, rectangle.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
||||
|
||||
|
||||
// draw monkey
|
||||
size_t model_idx = 2; // 0 cube; 1 sphere; 2 monkey
|
||||
|
||||
push_constants.vertexBuffer = testMeshes[model_idx]->meshBuffers.vertexBufferAddress;
|
||||
|
||||
vkCmdPushConstants(cmd,
|
||||
_meshPipelineLayout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0,
|
||||
sizeof(GPUDrawPushConstants),
|
||||
&push_constants);
|
||||
|
||||
vkCmdBindIndexBuffer(cmd,
|
||||
testMeshes[model_idx]->meshBuffers.indexBuffer.buffer,
|
||||
0,
|
||||
VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(cmd,
|
||||
testMeshes[model_idx]->surfaces[0].count,
|
||||
1,
|
||||
testMeshes[model_idx]->surfaces[0].startIndex,
|
||||
0, 0);
|
||||
|
||||
vkCmdEndRendering(cmd);
|
||||
}
|
||||
|
||||
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, ¤tBackgroundEffect);
|
||||
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", ¤tBackgroundEffect,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 +280,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 +314,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 +371,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 +463,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 +474,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 +503,83 @@ void VulkanEngine::init_descriptors() {
|
|||
void VulkanEngine::init_pipelines()
|
||||
{
|
||||
init_background_pipelines();
|
||||
init_triangle_pipelines();
|
||||
init_mesh_pipeline();
|
||||
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 +604,229 @@ 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()
|
||||
void VulkanEngine::init_mesh_pipeline()
|
||||
{
|
||||
// 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 } };
|
||||
VkShaderModule triangleFragShader;
|
||||
if (!vkutil::load_shader_module("colored_triangle.frag.spv", _device, &triangleFragShader)) {
|
||||
std::print("Error when building the triangle fragment shader module");
|
||||
}
|
||||
else {
|
||||
std::print("Triangle fragment shader succesfully loaded");
|
||||
}
|
||||
|
||||
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;
|
||||
VkShaderModule triangleVertexShader;
|
||||
if (!vkutil::load_shader_module("colored_triangle_mesh.vert.spv", _device, &triangleVertexShader)) {
|
||||
std::print("Error when building the triangle vertex shader module");
|
||||
}
|
||||
else {
|
||||
std::print("Triangle vertex shader succesfully loaded");
|
||||
}
|
||||
|
||||
VkDescriptorPool imguiPool;
|
||||
VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool));
|
||||
VkPushConstantRange bufferRange{
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = 0,
|
||||
.size = sizeof(GPUDrawPushConstants),
|
||||
};
|
||||
|
||||
// 2: initialize the imgui library
|
||||
ImGui::CreateContext();
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_info = vkinit::pipeline_layout_create_info();
|
||||
pipeline_layout_info.pPushConstantRanges = &bufferRange;
|
||||
pipeline_layout_info.pushConstantRangeCount = 1;
|
||||
|
||||
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;
|
||||
VK_CHECK(vkCreatePipelineLayout(_device, &pipeline_layout_info, nullptr, &_meshPipelineLayout));
|
||||
|
||||
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();
|
||||
PipelineBuilder pipelineBuilder;
|
||||
|
||||
_mainDeletionQueue.push_function([=,this]() {
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
vkDestroyDescriptorPool(_device, imguiPool, nullptr);
|
||||
pipelineBuilder._pipelineLayout = _meshPipelineLayout;
|
||||
pipelineBuilder.set_shaders(triangleVertexShader, triangleFragShader);
|
||||
pipelineBuilder.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
|
||||
pipelineBuilder.set_polygon_mode(VK_POLYGON_MODE_FILL);
|
||||
pipelineBuilder.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
|
||||
pipelineBuilder.set_multisampling_none();
|
||||
pipelineBuilder.disable_blending();
|
||||
pipelineBuilder.disable_depthtest();
|
||||
pipelineBuilder.set_color_attachment_format(_drawImage.imageFormat);
|
||||
pipelineBuilder.set_depth_format(VK_FORMAT_UNDEFINED);
|
||||
|
||||
_meshPipeline = pipelineBuilder.build_pipeline(_device);
|
||||
vkDestroyShaderModule(_device, triangleFragShader, nullptr);
|
||||
vkDestroyShaderModule(_device, triangleVertexShader, nullptr);
|
||||
|
||||
_mainDeletionQueue.push_function([&]() {
|
||||
vkDestroyPipelineLayout(_device, _meshPipelineLayout, nullptr);
|
||||
vkDestroyPipeline(_device, _meshPipeline, nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void VulkanEngine::draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView)
|
||||
void VulkanEngine::init_triangle_pipelines()
|
||||
{
|
||||
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
VkShaderModule triangleFragShader;
|
||||
|
||||
VkRenderingInfo renderInfo = vkinit::rendering_info(_swapchainExtent, &colorAttachment, nullptr);
|
||||
if(!vkutil::load_shader_module("colored_triangle.frag.spv",_device, &triangleFragShader)) {
|
||||
std::print("Error when building the triangle fragment shaders module");
|
||||
} else {
|
||||
std::print("Triangle fragment shader successfully loaded");
|
||||
}
|
||||
|
||||
vkCmdBeginRendering(cmd, &renderInfo);
|
||||
VkShaderModule triangleVertexShader;
|
||||
if(!vkutil::load_shader_module("colored_triangle.vert.spv", _device, &triangleVertexShader)) {
|
||||
std::println("Error when building the triangle, vertex shader module");
|
||||
} else {
|
||||
std::println("Triangle vertex shader successfully loaded");
|
||||
}
|
||||
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd);
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_info = vkinit::pipeline_layout_create_info();
|
||||
|
||||
vkCmdEndRendering(cmd);
|
||||
VK_CHECK(vkCreatePipelineLayout(_device, &pipeline_layout_info, nullptr, &_trianglePipelineLayout));
|
||||
|
||||
PipelineBuilder pipelineBuilder;
|
||||
|
||||
pipelineBuilder._pipelineLayout = _trianglePipelineLayout;
|
||||
pipelineBuilder.set_shaders(triangleVertexShader, triangleFragShader);
|
||||
pipelineBuilder.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
|
||||
pipelineBuilder.set_polygon_mode(VK_POLYGON_MODE_FILL);
|
||||
pipelineBuilder.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
|
||||
pipelineBuilder.set_multisampling_none();
|
||||
pipelineBuilder.disable_blending();
|
||||
pipelineBuilder.disable_depthtest();
|
||||
|
||||
// connect the image format we will drw into, from draw image
|
||||
pipelineBuilder.set_color_attachment_format(_drawImage.imageFormat);
|
||||
pipelineBuilder.set_depth_format(VK_FORMAT_UNDEFINED);
|
||||
|
||||
_trianglePipeline = pipelineBuilder.build_pipeline(_device);
|
||||
|
||||
vkDestroyShaderModule(_device, triangleFragShader, nullptr);
|
||||
vkDestroyShaderModule(_device, triangleVertexShader, nullptr);
|
||||
|
||||
_mainDeletionQueue.push_function([&]() {
|
||||
vkDestroyPipelineLayout(_device, _trianglePipelineLayout, nullptr);
|
||||
vkDestroyPipeline(_device, _trianglePipeline, nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
AllocatedBuffer VulkanEngine::create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage)
|
||||
{
|
||||
VkBufferCreateInfo bufferInfo{
|
||||
.sType=VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = allocSize,
|
||||
.usage = usage,
|
||||
};
|
||||
|
||||
VmaAllocationCreateInfo vmaallocInfo{
|
||||
.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||
.usage = memoryUsage,
|
||||
};
|
||||
|
||||
AllocatedBuffer newBuffer;
|
||||
|
||||
VK_CHECK(vmaCreateBuffer(_allocator, &bufferInfo,
|
||||
&vmaallocInfo, &newBuffer.buffer,
|
||||
&newBuffer.allocation, &newBuffer.info));
|
||||
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
void VulkanEngine::destroy_buffer(const AllocatedBuffer& buffer)
|
||||
{
|
||||
vmaDestroyBuffer(_allocator, buffer.buffer, buffer.allocation);
|
||||
}
|
||||
|
||||
GPUMeshBuffers VulkanEngine::uploadMesh(std::span<uint32_t> indices, std::span<Vertex> vertices)
|
||||
{
|
||||
const size_t vertexBufferSize = vertices.size() * sizeof(Vertex);
|
||||
const size_t indexBufferSize = indices.size() * sizeof(uint32_t);
|
||||
|
||||
GPUMeshBuffers newSurface;
|
||||
|
||||
newSurface.vertexBuffer = create_buffer(
|
||||
vertexBufferSize,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
|
||||
VkBufferDeviceAddressInfo deviceAddressInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
||||
.buffer = newSurface.vertexBuffer.buffer
|
||||
};
|
||||
|
||||
newSurface.vertexBufferAddress = vkGetBufferDeviceAddress(_device, &deviceAddressInfo);
|
||||
|
||||
newSurface.indexBuffer = create_buffer(indexBufferSize,
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
|
||||
AllocatedBuffer staging = create_buffer(vertexBufferSize + indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
|
||||
void* data = staging.allocation->GetMappedData();
|
||||
|
||||
memcpy(data, vertices.data(), vertexBufferSize);
|
||||
memcpy((char *)data + vertexBufferSize, indices.data(), indexBufferSize);
|
||||
|
||||
immediate_submit([&](VkCommandBuffer cmd) {
|
||||
VkBufferCopy vertexCopy{
|
||||
.srcOffset = 0,
|
||||
.dstOffset = 0,
|
||||
.size = vertexBufferSize,
|
||||
};
|
||||
|
||||
vkCmdCopyBuffer(cmd, staging.buffer,
|
||||
newSurface.vertexBuffer.buffer, 1,
|
||||
&vertexCopy);
|
||||
|
||||
VkBufferCopy indexCopy{
|
||||
.srcOffset = vertexBufferSize,
|
||||
.dstOffset = 0,
|
||||
.size = indexBufferSize,
|
||||
};
|
||||
|
||||
vkCmdCopyBuffer(cmd, staging.buffer,
|
||||
newSurface.indexBuffer.buffer, 1,
|
||||
&indexCopy);
|
||||
});
|
||||
|
||||
destroy_buffer(staging);
|
||||
|
||||
return newSurface;
|
||||
}
|
||||
|
||||
void VulkanEngine::init_default_data() {
|
||||
std::array<Vertex,4> rect_vertices;
|
||||
|
||||
rect_vertices[0].position = {0.5,-0.5, 0};
|
||||
rect_vertices[1].position = {0.5,0.5, 0};
|
||||
rect_vertices[2].position = {-0.5,-0.5, 0};
|
||||
rect_vertices[3].position = {-0.5,0.5, 0};
|
||||
|
||||
rect_vertices[0].color = {0,0, 0,1};
|
||||
rect_vertices[1].color = { 0.5,0.5,0.5 ,1};
|
||||
rect_vertices[2].color = { 1,0, 0,1 };
|
||||
rect_vertices[3].color = { 0,1, 0,1 };
|
||||
|
||||
std::array<uint32_t,6> rect_indices;
|
||||
|
||||
rect_indices[0] = 0;
|
||||
rect_indices[1] = 1;
|
||||
rect_indices[2] = 2;
|
||||
|
||||
rect_indices[3] = 2;
|
||||
rect_indices[4] = 1;
|
||||
rect_indices[5] = 3;
|
||||
|
||||
rectangle = uploadMesh(rect_indices, rect_vertices);
|
||||
|
||||
auto basicmesh = loadGltfMeshes(this, "basicmesh.glb");
|
||||
assert(basicmesh != std::nullopt && "Failed to load basicmesh.glb");
|
||||
|
||||
testMeshes = *basicmesh;
|
||||
|
||||
_mainDeletionQueue.push_function([&](){
|
||||
destroy_buffer(rectangle.indexBuffer);
|
||||
destroy_buffer(rectangle.vertexBuffer);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
52
vk_engine.h
52
vk_engine.h
|
|
@ -5,23 +5,14 @@
|
|||
|
||||
#include <vk_types.h>
|
||||
#include <vk_descriptors.h>
|
||||
#include "vk_gui.h"
|
||||
#include "vk_loader.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 +39,6 @@ struct FrameData {
|
|||
DeletionQueue _deletionQueue;
|
||||
};
|
||||
|
||||
constexpr unsigned int FRAME_OVERLAP=2;
|
||||
|
||||
class VulkanEngine {
|
||||
public:
|
||||
|
|
@ -58,7 +48,7 @@ public:
|
|||
VkPipeline _gradientPipeline;
|
||||
VkPipelineLayout _gradientPipelineLayout;
|
||||
|
||||
DescriptorAllocator globalDescriptorAllocator;
|
||||
DescriptorAllocator _globalDescriptorAllocator;
|
||||
VkDescriptorSet _drawImageDescriptors;
|
||||
VkDescriptorSetLayout _drawImageDescriptorLayout;
|
||||
|
||||
|
|
@ -77,6 +67,7 @@ public:
|
|||
std::vector<VkImageView> _swapchainImageViews;
|
||||
VkExtent2D _swapchainExtent;
|
||||
|
||||
|
||||
// VMA stuff
|
||||
VmaAllocator _allocator;
|
||||
|
||||
|
|
@ -104,6 +95,16 @@ public:
|
|||
// imgui shader stuff
|
||||
std::vector<ComputeEffect> backgroundEffects;
|
||||
int currentBackgroundEffect{0};
|
||||
VkPipelineLayout _trianglePipelineLayout;
|
||||
VkPipeline _trianglePipeline;
|
||||
VkPipelineLayout _meshPipelineLayout;
|
||||
VkPipeline _meshPipeline;
|
||||
|
||||
GPUMeshBuffers rectangle;
|
||||
std::vector<std::shared_ptr<MeshAsset>> testMeshes;
|
||||
|
||||
// ZED's REFACTOR
|
||||
VkGUI _gui;
|
||||
|
||||
static VulkanEngine& Get();
|
||||
|
||||
|
|
@ -121,6 +122,11 @@ public:
|
|||
|
||||
void immediate_submit(std::function<void(VkCommandBuffer cmd)>&& function);
|
||||
|
||||
Transaction begin_transaction();
|
||||
void commit_transaction(Transaction& cmd);
|
||||
|
||||
GPUMeshBuffers uploadMesh(std::span<uint32_t> indices, std::span<Vertex> vertices);
|
||||
|
||||
private:
|
||||
void init_vulkan();
|
||||
void init_swapchain();
|
||||
|
|
@ -129,11 +135,19 @@ private:
|
|||
void init_descriptors();
|
||||
void init_pipelines();
|
||||
void init_background_pipelines();
|
||||
void init_imgui();
|
||||
void init_shaders();
|
||||
void init_triangle_pipelines();
|
||||
void init_mesh_pipeline();
|
||||
void init_default_data();
|
||||
|
||||
void load_shader(const char *file_name, const char *entry_point, ComputeEffect data);
|
||||
|
||||
void create_swapchain(uint32_t width, uint32_t height);
|
||||
AllocatedBuffer create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage);
|
||||
|
||||
void destroy_swapchain();
|
||||
void destroy_buffer(const AllocatedBuffer& buffer);
|
||||
void draw_background(VkCommandBuffer cmd);
|
||||
void draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView);
|
||||
void render_imgui();
|
||||
void draw_geometry(VkCommandBuffer cmd);
|
||||
|
||||
};
|
||||
|
|
|
|||
151
vk_gui.cpp
Normal file
151
vk_gui.cpp
Normal 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
18
vk_gui.h
Normal 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();
|
||||
};
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,191 +1,139 @@
|
|||
#include <vk_initializers.h>
|
||||
#include <vulkan/vk_enum_string_helper.h>
|
||||
#include "trash_test.hpp"
|
||||
|
||||
nlohmann::json DATA = nlohmann::json::parse(R"(
|
||||
{
|
||||
"VkSemaphoreCreateInfo": {
|
||||
"draw": {
|
||||
"sType": 9
|
||||
}
|
||||
},
|
||||
"VkFenceCreateInfo": {
|
||||
"draw": {
|
||||
"sType": 8
|
||||
}
|
||||
},
|
||||
"VkImageViewCreateInfo": {
|
||||
"draw": {
|
||||
"sType": 15,
|
||||
"viewType": 1,
|
||||
"subresourceRange.baseMipLevel": 0,
|
||||
"subresourceRange.levelCount": 1,
|
||||
"subresourceRange.baseArrayLayer": 0,
|
||||
"subresourceRange.layerCount": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
)");
|
||||
|
||||
template<typename COMPONENT> COMPONENT load(nlohmann::json &data, const std::string& profile) {
|
||||
COMPONENT result{};
|
||||
auto& type_stuff = data[NameOf<COMPONENT>::name];
|
||||
auto& profile_data = type_stuff[profile];
|
||||
nlohmann::from_json(profile_data, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
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*/)
|
||||
{
|
||||
auto info = load<VkFenceCreateInfo>(DATA, "draw");
|
||||
info.flags = flags;
|
||||
return info;
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||
.flags = flags
|
||||
};
|
||||
}
|
||||
|
||||
VkSemaphoreCreateInfo vkinit::semaphore_create_info(VkSemaphoreCreateFlags flags/*=0*/)
|
||||
{
|
||||
auto info = load<VkSemaphoreCreateInfo>(DATA, "draw");
|
||||
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)
|
||||
{
|
||||
auto info = load<VkImageViewCreateInfo>(DATA, "draw");
|
||||
|
||||
info.image = image;
|
||||
info.format = format;
|
||||
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;
|
||||
|
|
@ -198,16 +146,38 @@ 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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
VkPipelineShaderStageCreateInfo vkinit::pipeline_shader_stage_create_info(VkShaderStageFlagBits stage, VkShaderModule shader, const char* entry) {
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = stage,
|
||||
.module = shader,
|
||||
.pName = entry,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
VkPipelineLayoutCreateInfo vkinit::pipeline_layout_create_info()
|
||||
{
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.setLayoutCount = 0,
|
||||
.pSetLayouts = nullptr,
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,5 +35,9 @@ namespace vkinit {
|
|||
VkImageView view, VkClearValue* clear ,VkImageLayout layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
VkRenderingInfo rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* depthAttachment);
|
||||
|
||||
VkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info(VkShaderStageFlagBits stage, VkShaderModule shader, const char* entry="main");
|
||||
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_create_info();
|
||||
}
|
||||
|
||||
|
|
|
|||
141
vk_loader.cpp
Normal file
141
vk_loader.cpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#include "vk_loader.h"
|
||||
#include "vendor/stb_image.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "vk_engine.h"
|
||||
#include "vk_initializers.h"
|
||||
#include "vk_types.h"
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <fastgltf/glm_element_traits.hpp>
|
||||
#include <fastgltf/core.hpp>
|
||||
#include <fastgltf/tools.hpp>
|
||||
|
||||
constexpr bool OverrideColors = true;
|
||||
|
||||
std::optional<std::vector<std::shared_ptr<MeshAsset>>> loadGltfMeshes(VulkanEngine* engine, std::filesystem::path filePath)
|
||||
{
|
||||
std::println("\nLoading GLTF: {}", filePath.string());
|
||||
auto data = fastgltf::GltfDataBuffer::FromPath(filePath);
|
||||
|
||||
if(data.error() != fastgltf::Error::None) {
|
||||
std::println("Failed to load glTF: {}={}\n",
|
||||
typeid(data.error()).name(),
|
||||
fastgltf::to_underlying(data.error()));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
constexpr auto gltfOptions = fastgltf::Options::LoadExternalBuffers;
|
||||
|
||||
fastgltf::Asset gltf{};
|
||||
fastgltf::Parser parser{};
|
||||
|
||||
auto load = parser.loadGltfBinary(data.get(), filePath.parent_path(), gltfOptions);
|
||||
|
||||
switch(load.error()) {
|
||||
case fastgltf::Error::None:
|
||||
gltf = std::move(load.get());
|
||||
break;
|
||||
case fastgltf::Error::InvalidGLB:
|
||||
std::println("fastgltf says Error::InvalidGLB {}", filePath.string());
|
||||
return std::nullopt;
|
||||
break;
|
||||
case fastgltf::Error::UnsupportedVersion:
|
||||
std::println("fastgltf says Error::UnsupportedVersion {}", filePath.string());
|
||||
return std::nullopt;
|
||||
break;
|
||||
case fastgltf::Error::InvalidPath:
|
||||
std::println("fastgltf says Error::UnsupportedVersion {}",
|
||||
filePath.string());
|
||||
return std::nullopt;
|
||||
break;
|
||||
default:
|
||||
std::println("Unknown fastgltf error loading {}", filePath.string());
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<MeshAsset>> meshes;
|
||||
// use the same vectors for all meshes
|
||||
std::vector<uint32_t> indices;
|
||||
std::vector<Vertex> vertices;
|
||||
|
||||
for(auto& mesh : gltf.meshes) {
|
||||
MeshAsset newmesh;
|
||||
newmesh.name = mesh.name;
|
||||
|
||||
indices.clear();
|
||||
indices.clear();
|
||||
|
||||
for(auto&& p : mesh.primitives) {
|
||||
auto& indexAccessor = gltf.accessors[p.indicesAccessor.value()];
|
||||
|
||||
GeoSurface newSurface {
|
||||
.startIndex = (uint32_t)indices.size(),
|
||||
.count = (uint32_t)indexAccessor.count,
|
||||
};
|
||||
|
||||
size_t initial_vtx = vertices.size();
|
||||
|
||||
// load indices
|
||||
{
|
||||
indices.reserve(indices.size() + indexAccessor.count);
|
||||
fastgltf::iterateAccessor<std::uint32_t>(
|
||||
gltf, indexAccessor, [&](std::uint32_t idx) {
|
||||
indices.push_back(idx + initial_vtx);
|
||||
});
|
||||
}
|
||||
|
||||
// load vertex positions
|
||||
{
|
||||
fastgltf::Accessor& posAccessor = gltf.accessors[
|
||||
p.findAttribute("POSITIONS")->accessorIndex];
|
||||
vertices.resize(vertices.size() + posAccessor.count);
|
||||
|
||||
fastgltf::iterateAccessorWithIndex<glm::vec3>(
|
||||
gltf, posAccessor, [&](glm::vec3 v, size_t index)
|
||||
{
|
||||
vertices[initial_vtx + index] = {
|
||||
.position = v,
|
||||
.uv_x = 0,
|
||||
.normal = {1, 0, 0},
|
||||
.uv_y = 0,
|
||||
.color = glm::vec4{1.0f},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// load vertex normals
|
||||
auto normals = p.findAttribute("NORMA:");
|
||||
if(normals != p.attributes.end()) {
|
||||
fastgltf::iterateAccessorWithIndex<glm::vec3>(
|
||||
gltf, gltf.accessors[(*normals).accessorIndex],
|
||||
[&](glm::vec3 v, size_t index)
|
||||
{
|
||||
vertices[initial_vtx + index].normal = v;
|
||||
});
|
||||
}
|
||||
|
||||
auto uv = p.findAttribute("TEXCOORD_0");
|
||||
if(uv != p.attributes.end()) {
|
||||
fastgltf::iterateAccessorWithIndex<glm::vec2>(
|
||||
gltf, gltf.accessors[(*uv).accessorIndex],
|
||||
[&](glm::vec2 v, size_t index) {
|
||||
vertices[initial_vtx + index].uv_x = v.x;
|
||||
vertices[initial_vtx + index].uv_y = v.y;
|
||||
});
|
||||
}
|
||||
|
||||
if(OverrideColors) {
|
||||
for(Vertex& vtx : vertices) {
|
||||
vtx.color = glm::vec4(vtx.normal, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
newmesh.meshBuffers = engine->uploadMesh(indices, vertices);
|
||||
meshes.emplace_back(std::make_shared<MeshAsset>(std::move(newmesh)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return meshes;
|
||||
}
|
||||
22
vk_loader.h
Normal file
22
vk_loader.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <vk_types.h>
|
||||
#include <unordered_map>
|
||||
#include <filesystem>
|
||||
|
||||
struct GeoSurface {
|
||||
uint32_t startIndex;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct MeshAsset {
|
||||
std::string name;
|
||||
|
||||
std::vector<GeoSurface> surfaces;
|
||||
GPUMeshBuffers meshBuffers;
|
||||
};
|
||||
|
||||
class VulkanEngine;
|
||||
|
||||
std::optional<std::vector<std::shared_ptr<MeshAsset>>> loadGltfMeshes(VulkanEngine* engine, std::filesystem::path filePath);
|
||||
|
||||
174
vk_pipelines.cpp
174
vk_pipelines.cpp
|
|
@ -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) {
|
||||
|
|
@ -40,3 +40,165 @@ bool vkutil::load_shader_module(const char* filePath,
|
|||
*outShaderModule = shaderModule;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PipelineBuilder::clear() {
|
||||
// clear all of the structs we need back to 0 with their correct stype
|
||||
|
||||
_inputAssembly = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
|
||||
_rasterizer = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
|
||||
|
||||
_colorBlendAttachment = {};
|
||||
|
||||
_multisampling = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||
|
||||
_pipelineLayout = {};
|
||||
|
||||
_depthStencil = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
|
||||
|
||||
_renderInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO };
|
||||
|
||||
_shaderStages.clear();
|
||||
}
|
||||
|
||||
VkPipeline PipelineBuilder::build_pipeline(VkDevice device)
|
||||
{
|
||||
VkPipelineViewportStateCreateInfo viewportState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1,
|
||||
};
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo colorBlending{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||
.logicOpEnable = VK_FALSE,
|
||||
.logicOp = VK_LOGIC_OP_COPY,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &_colorBlendAttachment,
|
||||
};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo _vertexInputInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
|
||||
};
|
||||
|
||||
VkDynamicState state[] = {
|
||||
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR
|
||||
};
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.dynamicStateCount = 2,
|
||||
// ZED: we don't need to do this? state is also &state[0]
|
||||
.pDynamicStates = &state[0],
|
||||
};
|
||||
|
||||
// build the actual pipeline
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = &_renderInfo,
|
||||
.stageCount = (uint32_t)_shaderStages.size(),
|
||||
.pStages = _shaderStages.data(),
|
||||
.pVertexInputState = &_vertexInputInfo,
|
||||
.pInputAssemblyState = &_inputAssembly,
|
||||
.pViewportState = &viewportState,
|
||||
.pRasterizationState = &_rasterizer,
|
||||
.pMultisampleState = &_multisampling,
|
||||
.pDepthStencilState = &_depthStencil,
|
||||
.pColorBlendState = &colorBlending,
|
||||
.pDynamicState = &dynamicInfo,
|
||||
.layout = _pipelineLayout,
|
||||
};
|
||||
|
||||
// its easy to error out on create graphics pipeline, so we handle it a bit
|
||||
// better than the common VK_CHECK case
|
||||
|
||||
VkPipeline newPipeline;
|
||||
auto works = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &newPipeline);
|
||||
|
||||
if(works != VK_SUCCESS) {
|
||||
std::println("failed to create pipeline");
|
||||
return VK_NULL_HANDLE;
|
||||
} else {
|
||||
return newPipeline;
|
||||
}
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_shaders(VkShaderModule vertexShader, VkShaderModule fragmentShader)
|
||||
{
|
||||
_shaderStages.clear();
|
||||
|
||||
_shaderStages.push_back(
|
||||
vkinit::pipeline_shader_stage_create_info(
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
vertexShader));
|
||||
|
||||
_shaderStages.push_back(
|
||||
vkinit::pipeline_shader_stage_create_info(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
fragmentShader));
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_input_topology(VkPrimitiveTopology topology)
|
||||
{
|
||||
_inputAssembly.topology = topology;
|
||||
_inputAssembly.primitiveRestartEnable = VK_FALSE;
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_polygon_mode(VkPolygonMode mode)
|
||||
{
|
||||
_rasterizer.polygonMode = mode;
|
||||
_rasterizer.lineWidth = 1.0f;
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_cull_mode(VkCullModeFlags cullMode, VkFrontFace frontFace)
|
||||
{
|
||||
_rasterizer.cullMode = cullMode;
|
||||
_rasterizer.frontFace = frontFace;
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_multisampling_none()
|
||||
{
|
||||
_multisampling.sampleShadingEnable = VK_FALSE;
|
||||
_multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
_multisampling.minSampleShading = 1.0f;
|
||||
_multisampling.pSampleMask = nullptr;
|
||||
_multisampling.alphaToCoverageEnable = VK_FALSE;
|
||||
_multisampling.alphaToOneEnable = VK_FALSE;
|
||||
}
|
||||
|
||||
void PipelineBuilder::disable_blending()
|
||||
{
|
||||
_colorBlendAttachment.colorWriteMask =
|
||||
VK_COLOR_COMPONENT_R_BIT
|
||||
| VK_COLOR_COMPONENT_G_BIT
|
||||
| VK_COLOR_COMPONENT_B_BIT
|
||||
| VK_COLOR_COMPONENT_A_BIT;
|
||||
|
||||
_colorBlendAttachment.blendEnable = VK_FALSE;
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_color_attachment_format(VkFormat format)
|
||||
{
|
||||
_colorAttachmentFormat = format;
|
||||
_renderInfo.colorAttachmentCount = 1;
|
||||
_renderInfo.pColorAttachmentFormats = &_colorAttachmentFormat;
|
||||
}
|
||||
|
||||
void PipelineBuilder::set_depth_format(VkFormat format)
|
||||
{
|
||||
_renderInfo.depthAttachmentFormat = format;
|
||||
}
|
||||
|
||||
void PipelineBuilder::disable_depthtest()
|
||||
{
|
||||
_depthStencil.depthTestEnable = VK_FALSE;
|
||||
_depthStencil.depthWriteEnable = VK_FALSE;
|
||||
_depthStencil.depthCompareOp = VK_COMPARE_OP_NEVER;
|
||||
_depthStencil.depthBoundsTestEnable = VK_FALSE;
|
||||
_depthStencil.stencilTestEnable = VK_FALSE;
|
||||
_depthStencil.front = {};
|
||||
_depthStencil.back = {};
|
||||
_depthStencil.minDepthBounds = 0.0f;
|
||||
_depthStencil.maxDepthBounds = 1.0f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,37 @@
|
|||
|
||||
#include "vk_types.h"
|
||||
|
||||
class PipelineBuilder {
|
||||
public:
|
||||
std::vector<VkPipelineShaderStageCreateInfo> _shaderStages;
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo _inputAssembly;
|
||||
VkPipelineRasterizationStateCreateInfo _rasterizer;
|
||||
VkPipelineColorBlendAttachmentState _colorBlendAttachment;
|
||||
VkPipelineMultisampleStateCreateInfo _multisampling;
|
||||
VkPipelineLayout _pipelineLayout;
|
||||
VkPipelineDepthStencilStateCreateInfo _depthStencil;
|
||||
VkPipelineRenderingCreateInfo _renderInfo;
|
||||
VkFormat _colorAttachmentFormat;
|
||||
|
||||
PipelineBuilder() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
VkPipeline build_pipeline(VkDevice device);
|
||||
void set_shaders(VkShaderModule vertexShader, VkShaderModule fragmentShader);
|
||||
void set_input_topology(VkPrimitiveTopology topology);
|
||||
void set_polygon_mode(VkPolygonMode mode);
|
||||
void set_cull_mode(VkCullModeFlags cullMode, VkFrontFace frontFace);
|
||||
void set_multisampling_none();
|
||||
void disable_blending();
|
||||
void set_color_attachment_format(VkFormat format);
|
||||
void set_depth_format(VkFormat format);
|
||||
void disable_depthtest();
|
||||
};
|
||||
|
||||
namespace vkutil {
|
||||
bool load_shader_module(const char* filePath,
|
||||
VkDevice device,
|
||||
|
|
|
|||
44
vk_types.h
44
vk_types.h
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <print>
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL 1
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
|
|
@ -30,6 +31,14 @@
|
|||
} while (0)
|
||||
|
||||
|
||||
constexpr unsigned int FRAME_OVERLAP=2;
|
||||
|
||||
struct AllocatedBuffer {
|
||||
VkBuffer buffer;
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo info;
|
||||
};
|
||||
|
||||
struct AllocatedImage {
|
||||
VkImage image;
|
||||
VkImageView imageView;
|
||||
|
|
@ -37,3 +46,38 @@ 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;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
glm::vec3 position;
|
||||
float uv_x;
|
||||
glm::vec3 normal;
|
||||
float uv_y;
|
||||
glm::vec4 color;
|
||||
};
|
||||
|
||||
struct GPUMeshBuffers {
|
||||
AllocatedBuffer indexBuffer;
|
||||
AllocatedBuffer vertexBuffer;
|
||||
VkDeviceAddress vertexBufferAddress;
|
||||
};
|
||||
|
||||
struct GPUDrawPushConstants {
|
||||
glm::mat4 worldMatrix;
|
||||
VkDeviceAddress vertexBuffer;
|
||||
};
|
||||
|
||||
|
|
|
|||
9
wraps/fastgltf.wrap
Normal file
9
wraps/fastgltf.wrap
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[wrap-git]
|
||||
directory=fastgltf
|
||||
url=https://github.com/spnda/fastgltf.git
|
||||
revision=v0.9.0
|
||||
depth=1
|
||||
method=cmake
|
||||
|
||||
[provide]
|
||||
fastgltf = fastgltf_dep
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
[wrap-file]
|
||||
directory = nlohmann_json-3.11.3
|
||||
lead_directory_missing = true
|
||||
source_url = https://github.com/nlohmann/json/releases/download/v3.11.3/include.zip
|
||||
source_filename = nlohmann_json-3.11.3.zip
|
||||
source_hash = a22461d13119ac5c78f205d3df1db13403e58ce1bb1794edc9313677313f4a9d
|
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/nlohmann_json_3.11.3-1/nlohmann_json-3.11.3.zip
|
||||
wrapdb_version = 3.11.3-1
|
||||
|
||||
[provide]
|
||||
nlohmann_json = nlohmann_json_dep
|
||||
13
wraps/simdjson.wrap
Normal file
13
wraps/simdjson.wrap
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[wrap-file]
|
||||
directory = simdjson-3.3.0
|
||||
source_url = https://github.com/simdjson/simdjson/archive/refs/tags/v3.3.0.tar.gz
|
||||
source_filename = simdjson-3.3.0.tar.gz
|
||||
source_hash = a8c9feff2f19c3ff281d42f0b6b4b18f02236513b99229756fa9a1b14787a58a
|
||||
patch_filename = simdjson_3.3.0-2_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/simdjson_3.3.0-2/get_patch
|
||||
patch_hash = 3c39f8a5abac17732b9599a416e6edb09f5f987bcf4e8b46808dbe88040eb40f
|
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/simdjson_3.3.0-2/simdjson-3.3.0.tar.gz
|
||||
wrapdb_version = 3.3.0-2
|
||||
|
||||
[provide]
|
||||
simdjson = simdjson_dep
|
||||
Loading…
Add table
Add a link
Reference in a new issue