WIP library for abstracting Vulkan API to later use in my projects (including MxEngine)
- loading obj and gltf objects (multiple submeshes, pbr materials)
- loading png, jpg, tga, bmp, dds, zlib-packed images (mip-maps, automatic format selection)
- virtual frames, staging buffers, mipmap generation (via blitImage)
- render graph with automatic attachment creation, descriptor set allocation and barrier placement
- imgui integration (with support of textures)
- vertex/fragment shaders, compute shaders, from-source shader compilation and reflection
- clone to your system using:
git clone --recurse-submodules https://github.com/vkdev-team/VulkanAbstractionLayer
- make sure you have Vulkan SDK installed (Vulkan 1.2 is recommended)
- build examples by running main
CMakeLists.txt
If you want to use the library in your CMake project:
add_subdirectory(VulkanAbstractionLayer)
target_include_directories(TARGET PUBLIC ${VULKAN_ABSTRACTION_LAYER_INCLUDE_DIR})
target_link_libraries(TARGET PUBLIC VulkanAbstractionLayer)
#include "VulkanAbstractionLayer/Window.h"
#include "VulkanAbstractionLayer/VulkanContext.h"
using namespace VulkanAbstractionLayer;
int main()
{
WindowCreateOptions windowOptions;
windowOptions.Position = { 300.0f, 100.0f };
windowOptions.Size = { 1280.0f, 720.0f };
Window window(windowOptions);
VulkanContextCreateOptions vulkanOptions;
vulkanOptions.VulkanApiMajorVersion = 1;
vulkanOptions.VulkanApiMinorVersion = 2;
vulkanOptions.Extensions = window.GetRequiredExtensions();
vulkanOptions.Layers = { "VK_LAYER_KHRONOS_validation" };
VulkanContext Vulkan(vulkanOptions);
SetCurrentVulkanContext(Vulkan);
ContextInitializeOptions deviceOptions;
deviceOptions.PreferredDeviceType = DeviceType::DISCRETE_GPU;
Vulkan.InitializeContext(window.CreateWindowSurface(Vulkan), deviceOptions);
window.OnResize([&Vulkan](Window& window, Vector2 size) mutable
{
Vulkan.RecreateSwapchain((uint32_t)size.x, (uint32_t)size.y);
});
while (!window.ShouldClose())
{
window.PollEvents();
if(Vulkan.IsRenderingEnabled())
{
Vulkan.StartFrame();
// rendering
Vulkan.EndFrame();
}
}
return 0;
}
Describe RenderPass (can be abstract, not necessary containing actual shader):
class SomeRenderPass : public RenderPass
{
public:
OpaqueRenderPass()
{
// initialization code
}
virtual void SetupPipeline(PipelineState pipeline) override
{
// load shader
pipeline.Shader = std::make_unique<GraphicShader>(
ShaderLoader::LoadFromSource("vertex.glsl", ShaderType::VERTEX, ShaderLanguage::GLSL),
ShaderLoader::LoadFromSource("fragment.glsl", ShaderType::FRAGMENT, ShaderLanguage::GLSL)
);
// describe vertex buffer bindings
pipeline.VertexBindings = {
VertexBinding{
VertexBinding::Rate::PER_VERTEX,
3,
},
VertexBinding{
VertexBinding::Rate::PER_INSTANCE,
2,
},
};
// describe descriptor bindings per descriptor set
pipeline.DescriptorBindings
.Bind(0, "UniformBuffer", UniformType::UNIFORM_BUFFER)
.Bind(1, textureSampler, UniformType::SAMPLER)
.Bind(2, "Textures", UniformType::SAMPLED_IMAGE);
// add output attachments
pipeline.AddOutputAttachment("Output", ClearColor{ 0.5f, 0.8f, 1.0f, 1.0f });
pipeline.AddOutputAttachment("OutputDepth", ClearDepthSpencil{ });
}
virtual void ResolveResources(ResolveState state) override
{
// resolve resource names to exact resources
state.Resolve("UniformBuffer", uniformBuffer);
state.Resolve("Textures", textures);
}
virtual void OnRender(RenderPassState state) override
{
state.Commands.SetRenderArea(state.GetAttachment("Output"));
// draw some stuff
state.Commands.BindVertexBuffers(vertexBuffer);
state.Commands.BindIndexBufferUInt32(indexBuffer);
state.Commands.PushConstants(state.Pass, &pushConstants);
state.Commands.DrawIndexed(indexCount, instanceCount);
}
};
Build render graph from render passes:
// some passes like ImGuiRenderPass are supported out of box
RenderGraphBuilder renderGraphBuilder;
renderGraphBuilder
.AddRenderPass("SomePass", std::make_unique<SomeRenderPass>(parameters))
.AddRenderPass("ImGuiPass", std::make_unique<ImGuiRenderPass>("Output"))
.SetOutputName("Output");
RenderGraph renderGraph = renderGraphBuilder.Build();
Execute render graph each frame:
auto& Vulkan = GetCurrentVulkanContext();
while (!window.ShouldClose())
{
window.PollEvents();
if (Vulkan.IsRenderingEnabled())
{
Vulkan.StartFrame();
renderGraph.Execute(Vulkan.GetCurrentCommandBuffer());
renderGraph.Present(Vulkan.GetCurrentCommandBuffer(), Vulkan.AcquireCurrentSwapchainImage(ImageUsage::TRANSFER_DISTINATION));
Vulkan.EndFrame();
}
}
simple shadow mapping ibl lighting area light from LTC paper textured light from LTC paper cloth simulation based on compute shader
terrain.mp4
dynamic terrain tess level based on eye distance Rigid body simulation based on impulse method, project link: https://github.com/fall2019/RigidBodySim