refactor(cleanup): do not link Vulkan

This commit is contained in:
PancakeTAS 2025-12-06 22:07:20 +01:00
parent 75f02a97f5
commit 0a0c07e183
No known key found for this signature in database
38 changed files with 563 additions and 272 deletions

View file

@ -110,9 +110,9 @@ ManagedShader ManagedShaderBuilder::build(const vk::Vulkan& vk,
};
}
void ManagedShader::dispatch(const vk::CommandBuffer& cmd,
void ManagedShader::dispatch(const vk::Vulkan& vk, const vk::CommandBuffer& cmd,
VkExtent2D extent) const {
cmd.dispatch(this->shader,
cmd.dispatch(vk, this->shader,
this->descriptorSet,
this->barriers,
extent.width, extent.height, 1

View file

@ -18,10 +18,12 @@ namespace ls {
friend class ManagedShaderBuilder;
public:
/// dispatch the managed shader
/// @param vk the vulkan instance
/// @param cmd command buffer to use
/// @param extent dispatch size
/// @throws ls::vulkan_error on failure
void dispatch(const vk::CommandBuffer& cmd, VkExtent2D extent) const;
void dispatch(const vk::Vulkan& vk,
const vk::CommandBuffer& cmd, VkExtent2D extent) const;
private:
ls::R<const vk::Shader> shader;

View file

@ -122,10 +122,11 @@ Instance::Instance(
const std::function<bool(const std::string&)>& devicePicker,
const std::filesystem::path& shaderDllPath,
bool allowLowPrecision) {
const auto selectFunc = [&devicePicker](const std::vector<VkPhysicalDevice>& devices) {
const auto selectFunc = [&devicePicker](const vk::VulkanInstanceFuncs funcs,
const std::vector<VkPhysicalDevice>& devices) {
for (const auto& device : devices) {
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(device, &props);
funcs.GetPhysicalDeviceProperties(device, &props);
std::array<char, 256> devname = std::to_array(props.deviceName);
devname[255] = '\0'; // ensure null-termination
@ -440,22 +441,22 @@ ContextImpl::ContextImpl(const InstanceImpl& instance,
// initialize all images
const vk::CommandBuffer cmdbuf{ctx.vk};
cmdbuf.prepareImage(this->blackImage);
mipmaps.prepare(cmdbuf);
cmdbuf.prepareImage(ctx.vk, this->blackImage);
mipmaps.prepare(ctx.vk, cmdbuf);
for (size_t i = 0; i < 7; ++i) {
alpha0.at(i).prepare(cmdbuf);
alpha1.at(i).prepare(cmdbuf);
alpha0.at(i).prepare(ctx.vk, cmdbuf);
alpha1.at(i).prepare(ctx.vk, cmdbuf);
}
beta0.prepare(cmdbuf);
beta1.prepare(cmdbuf);
beta0.prepare(ctx.vk, cmdbuf);
beta1.prepare(ctx.vk, cmdbuf);
for (const auto& pass : this->passes) {
for (size_t i = 0; i < 7; ++i) {
pass.gamma0.at(i).prepare(cmdbuf);
pass.gamma1.at(i).prepare(cmdbuf);
pass.gamma0.at(i).prepare(ctx.vk, cmdbuf);
pass.gamma1.at(i).prepare(ctx.vk, cmdbuf);
if (i < 4) continue;
pass.delta0.at(i - 4).prepare(cmdbuf);
pass.delta1.at(i - 4).prepare(cmdbuf);
pass.delta0.at(i - 4).prepare(ctx.vk, cmdbuf);
pass.delta1.at(i - 4).prepare(ctx.vk, cmdbuf);
}
}
cmdbuf.submit(ctx.vk); // wait for completion
@ -477,7 +478,7 @@ void Instance::scheduleFrames(Context& context) {
}
#ifdef LSFGVK__RENDERDOC_INTEGRATION
if (impl->getRenderDocAPI()) {
vkDeviceWaitIdle(impl->getVulkan().dev());
impl->getVulkan().df().DeviceWaitIdle(impl->getVulkan().dev());
impl->getRenderDocAPI()->EndFrameCapture(
RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(impl->getVulkan().inst()),
nullptr);
@ -490,13 +491,13 @@ void Context::scheduleFrames() {
vk::CommandBuffer& cmdbuf = this->cmdbufs.at(this->cmdbuf_idx++ % this->cmdbufs.size());
cmdbuf = vk::CommandBuffer(this->ctx.vk);
this->mipmaps.render(cmdbuf, this->fidx);
this->mipmaps.render(ctx.vk, cmdbuf, this->fidx);
for (size_t i = 0; i < 7; ++i) {
this->alpha0.at(6 - i).render(cmdbuf);
this->alpha1.at(6 - i).render(cmdbuf, this->fidx);
this->alpha0.at(6 - i).render(ctx.vk, cmdbuf);
this->alpha1.at(6 - i).render(ctx.vk, cmdbuf, this->fidx);
}
this->beta0.render(cmdbuf, this->fidx);
this->beta1.render(cmdbuf);
this->beta0.render(ctx.vk, cmdbuf, this->fidx);
this->beta1.render(ctx.vk, cmdbuf);
cmdbuf.submit(this->ctx.vk,
this->syncSemaphore, this->idx,
@ -512,14 +513,14 @@ void Context::scheduleFrames() {
const auto& pass = this->passes.at(i);
for (size_t j = 0; j < 7; j++) {
pass.gamma0.at(j).render(cmdbuf, this->fidx);
pass.gamma1.at(j).render(cmdbuf);
pass.gamma0.at(j).render(ctx.vk, cmdbuf, this->fidx);
pass.gamma1.at(j).render(ctx.vk, cmdbuf);
if (j < 4) continue;
pass.delta0.at(j - 4).render(cmdbuf, this->fidx);
pass.delta1.at(j - 4).render(cmdbuf);
pass.delta0.at(j - 4).render(ctx.vk, cmdbuf, this->fidx);
pass.delta1.at(j - 4).render(ctx.vk, cmdbuf);
}
pass.generate->render(cmdbuf, this->fidx);
pass.generate->render(ctx.vk, cmdbuf, this->fidx);
cmdbuf.submit(this->ctx.vk,
this->prepassSemaphore, this->idx - 1,
@ -540,7 +541,9 @@ void Instance::closeContext(const Context& context) {
throw lsfgvk::error("attempted to close unknown context",
std::runtime_error("no such context"));
vkDeviceWaitIdle(this->m_impl->getVulkan().dev());
const auto& vk = this->m_impl->getVulkan();
vk.df().DeviceWaitIdle(vk.dev());
this->m_contexts.erase(it);
}

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -53,20 +54,20 @@ Alpha0::Alpha0(const ls::Ctx& ctx,
this->dispatchExtent1 = ls::add_shift_extent(quarterExtent, 7, 3);
}
void Alpha0::prepare(const vk::CommandBuffer& cmd) const {
void Alpha0::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
// TODO: find a way to batch prepare
for (size_t i = 0; i < this->tempImages0.size(); i++) {
cmd.prepareImage(this->tempImages0.at(i));
cmd.prepareImage(this->tempImages1.at(i));
cmd.prepareImage(vk, this->tempImages0.at(i));
cmd.prepareImage(vk, this->tempImages1.at(i));
}
for (const auto& image : this->images)
cmd.prepareImage(image);
cmd.prepareImage(vk, image);
}
void Alpha0::render(const vk::CommandBuffer& cmd) const {
this->sets[0].dispatch(cmd, this->dispatchExtent0);
this->sets[1].dispatch(cmd, this->dispatchExtent0);
this->sets[2].dispatch(cmd, this->dispatchExtent1);
void Alpha0::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
this->sets[0].dispatch(vk, cmd, this->dispatchExtent0);
this->sets[1].dispatch(vk, cmd, this->dispatchExtent0);
this->sets[2].dispatch(vk, cmd, this->dispatchExtent1);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -22,12 +23,14 @@ namespace chains {
const vk::Image& sourceImage);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the pre-alpha shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
void render(const vk::CommandBuffer& cmd) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// get the generated images
/// @return vector of images

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -40,13 +41,13 @@ Alpha1::Alpha1(const ls::Ctx& ctx,
this->dispatchExtent = ls::add_shift_extent(quarterExtent, 7, 3);
}
void Alpha1::prepare(const vk::CommandBuffer& cmd) const {
void Alpha1::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& vec : this->images)
for (const auto& img : vec)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
}
void Alpha1::render(const vk::CommandBuffer& cmd, size_t idx) const {
void Alpha1::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {
// FIXME: iirc only one of the 7 instances of alpha1 requires 3 temporal images
this->sets[idx % 3].dispatch(cmd, dispatchExtent);
this->sets[idx % 3].dispatch(vk, cmd, dispatchExtent);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -22,13 +23,15 @@ namespace chains {
const std::vector<vk::Image>& sourceImages);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the alpha shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
/// @param idx frame index
void render(const vk::CommandBuffer& cmd, size_t idx) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
/// get the generated images
/// @return vector of images

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -37,11 +38,11 @@ Beta0::Beta0(const ls::Ctx& ctx,
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
}
void Beta0::prepare(const vk::CommandBuffer& cmd) const {
void Beta0::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& img : this->images)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
}
void Beta0::render(const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 3].dispatch(cmd, dispatchExtent);
void Beta0::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 3].dispatch(vk, cmd, dispatchExtent);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -22,13 +23,15 @@ namespace chains {
const std::vector<std::vector<vk::Image>>& sourceImages);
/// prepare the shaderchain initially
/// @param vk vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the beta shaderchain
/// @param vk vulkan instance
/// @param cmd command buffer
/// @param idx frame index
void render(const vk::CommandBuffer& cmd, size_t idx) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
/// get the generated images
/// @return vector of images

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <cstdint>
@ -61,18 +62,18 @@ Beta1::Beta1(const ls::Ctx& ctx,
this->dispatchExtent1 = ls::add_shift_extent(extent, 31, 5);
}
void Beta1::prepare(const vk::CommandBuffer& cmd) const {
void Beta1::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (size_t i = 0; i < 2; i++) {
cmd.prepareImage(this->tempImages0.at(i));
cmd.prepareImage(this->tempImages1.at(i));
cmd.prepareImage(vk, this->tempImages0.at(i));
cmd.prepareImage(vk, this->tempImages1.at(i));
}
for (const auto& img : this->images)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
}
void Beta1::render(const vk::CommandBuffer& cmd) const {
this->sets[0].dispatch(cmd, this->dispatchExtent0);
this->sets[1].dispatch(cmd, this->dispatchExtent0);
this->sets[2].dispatch(cmd, this->dispatchExtent0);
this->sets[3].dispatch(cmd, this->dispatchExtent1);
void Beta1::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
this->sets[0].dispatch(vk, cmd, this->dispatchExtent0);
this->sets[1].dispatch(vk, cmd, this->dispatchExtent0);
this->sets[2].dispatch(vk, cmd, this->dispatchExtent0);
this->sets[3].dispatch(vk, cmd, this->dispatchExtent1);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -22,12 +23,14 @@ namespace chains {
const std::vector<vk::Image>& sourceImages);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the beta shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
void render(const vk::CommandBuffer& cmd) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// get the generated images
/// @return vector of images

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -59,14 +60,14 @@ Delta0::Delta0(const ls::Ctx& ctx, size_t idx,
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
}
void Delta0::prepare(const vk::CommandBuffer& cmd) const {
void Delta0::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& img : this->images0)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
for (const auto& img : this->images1)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
}
void Delta0::render(const vk::CommandBuffer& cmd, size_t idx) const {
this->sets0[idx % 3].dispatch(cmd, dispatchExtent);
this->sets1[idx % 3].dispatch(cmd, dispatchExtent);
void Delta0::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {
this->sets0[idx % 3].dispatch(vk, cmd, dispatchExtent);
this->sets1[idx % 3].dispatch(vk, cmd, dispatchExtent);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -27,13 +28,15 @@ namespace chains {
const vk::Image& additionalInput1);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the delta shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
/// @param idx frame index
void render(const vk::CommandBuffer& cmd, size_t idx) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
/// get the generated images
/// @return vector of images

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -92,16 +93,16 @@ Delta1::Delta1(const ls::Ctx& ctx, size_t idx,
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
}
void Delta1::prepare(const vk::CommandBuffer& cmd) const {
void Delta1::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (size_t i = 0; i < this->tempImages0.size(); i++) {
cmd.prepareImage(this->tempImages0.at(i));
cmd.prepareImage(this->tempImages1.at(i));
cmd.prepareImage(vk, this->tempImages0.at(i));
cmd.prepareImage(vk, this->tempImages1.at(i));
}
cmd.prepareImage(*this->image0);
cmd.prepareImage(*this->image1);
cmd.prepareImage(vk, *this->image0);
cmd.prepareImage(vk, *this->image1);
}
void Delta1::render(const vk::CommandBuffer& cmd) const {
void Delta1::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& set : this->sets)
set.dispatch(cmd, dispatchExtent);
set.dispatch(vk, cmd, dispatchExtent);
}

View file

@ -5,6 +5,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -32,12 +33,14 @@ namespace chains {
const vk::Image& additionalInput2);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the gamma shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
void render(const vk::CommandBuffer& cmd) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// get the first generated image
/// @return image

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -40,11 +41,11 @@ Gamma0::Gamma0(const ls::Ctx& ctx, size_t idx,
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
}
void Gamma0::prepare(const vk::CommandBuffer& cmd) const {
void Gamma0::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& img : this->images)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
}
void Gamma0::render(const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 3].dispatch(cmd, dispatchExtent);
void Gamma0::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 3].dispatch(vk, cmd, dispatchExtent);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -25,13 +26,15 @@ namespace chains {
const vk::Image& additionalInput);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the gamma shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
/// @param idx frame index
void render(const vk::CommandBuffer& cmd, size_t idx) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
/// get the generated images
/// @return vector of images

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -61,15 +62,15 @@ Gamma1::Gamma1(const ls::Ctx& ctx, size_t idx,
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
}
void Gamma1::prepare(const vk::CommandBuffer& cmd) const {
void Gamma1::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (size_t i = 0; i < this->tempImages0.size(); i++) {
cmd.prepareImage(this->tempImages0.at(i));
cmd.prepareImage(this->tempImages1.at(i));
cmd.prepareImage(vk, this->tempImages0.at(i));
cmd.prepareImage(vk, this->tempImages1.at(i));
}
cmd.prepareImage(*this->image);
cmd.prepareImage(vk, *this->image);
}
void Gamma1::render(const vk::CommandBuffer& cmd) const {
void Gamma1::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& set : this->sets)
set.dispatch(cmd, dispatchExtent);
set.dispatch(vk, cmd, dispatchExtent);
}

View file

@ -5,6 +5,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <vector>
@ -28,12 +29,14 @@ namespace chains {
const vk::Image& additionalInput1);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the gamma shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
void render(const vk::CommandBuffer& cmd) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// get the generated image
/// @return image

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <utility>
@ -47,6 +48,6 @@ Generate::Generate(const ls::Ctx& ctx, size_t idx,
this->dispatchExtent = ls::add_shift_extent(ctx.sourceExtent, 15, 4);
}
void Generate::render(const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 2].dispatch(cmd, this->dispatchExtent);
void Generate::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 2].dispatch(vk, cmd, this->dispatchExtent);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -31,9 +32,10 @@ namespace chains {
const vk::Image& outputImage);
/// render the generate shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
/// @param idx frame index
void render(const vk::CommandBuffer& cmd, size_t idx) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
private:
std::vector<ls::ManagedShader> sets;
VkExtent2D dispatchExtent{};

View file

@ -3,6 +3,7 @@
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <cstdint>
@ -40,11 +41,11 @@ Mipmaps::Mipmaps(const ls::Ctx& ctx,
this->dispatchExtent = ls::add_shift_extent(ctx.flowExtent, 63, 6);
}
void Mipmaps::prepare(const vk::CommandBuffer& cmd) const {
void Mipmaps::prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const {
for (const auto& img : this->images)
cmd.prepareImage(img);
cmd.prepareImage(vk, img);
}
void Mipmaps::render(const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 2].dispatch(cmd, this->dispatchExtent);
void Mipmaps::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {
this->sets[idx % 2].dispatch(vk, cmd, this->dispatchExtent);
}

View file

@ -4,6 +4,7 @@
#include "../helpers/utils.hpp"
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
#include "lsfg-vk-common/vulkan/image.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <vector>
@ -23,13 +24,15 @@ namespace chains {
const std::pair<vk::Image, vk::Image>& sourceImages);
/// prepare the shaderchain initially
/// @param vk the vulkan instance
/// @param cmd command buffer
void prepare(const vk::CommandBuffer& cmd) const;
void prepare(const vk::Vulkan& vk, const vk::CommandBuffer& cmd) const;
/// render the mipmaps shaderchain
/// @param vk the vulkan instance
/// @param cmd command buffer
/// @param idx frame index
void render(const vk::CommandBuffer& cmd, size_t idx) const;
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
/// get the generated mipmap images
/// @return vector of images

View file

@ -15,5 +15,3 @@ add_library(lsfg-vk-common STATIC ${COMMON_SOURCES})
target_include_directories(lsfg-vk-common
PUBLIC include)
target_link_libraries(lsfg-vk-common
vulkan)

View file

@ -27,22 +27,32 @@ namespace vk {
CommandBuffer(const vk::Vulkan& vk);
/// initialize an image
/// @param vk the vulkan instance
/// @param image the image to initialize
/// @param clearColor optional clear color
void prepareImage(const vk::Image& image,
void prepareImage(const vk::Vulkan& vk,
const vk::Image& image,
const std::optional<VkClearColorValue>& clearColor = std::nullopt) const;
/// dispatch a compute shader
/// @param vk the vulkan instance
/// @param shader the compute shader
/// @param set the descriptor set
/// @param barriers image memory barriers to apply
/// @param x dispatch size in X
/// @param y dispatch size in Y
/// @param z dispatch size in Z
void dispatch(const vk::Shader& shader, const vk::DescriptorSet& set,
void dispatch(const vk::Vulkan& vk, const vk::Shader& shader, const vk::DescriptorSet& set,
const std::vector<vk::Barrier>& barriers,
uint32_t x, uint32_t y, uint32_t z) const;
/// copy buffer to image
/// @param vk the vulkan instance
/// @param buffer the source buffer
/// @param image the destination image
void copyBufferToImage(const vk::Vulkan& vk,
const vk::Buffer& buffer, const vk::Image& image) const;
/// submit the command buffer
/// @param vk the vulkan instance
/// @param waitSemaphore the semaphore to wait on
@ -58,11 +68,6 @@ namespace vk {
/// @param vk the vulkan instance
/// @throws ls::vulkan_error on failure
void submit(const vk::Vulkan& vk) const;
/// copy buffer to image
/// @param buffer the source buffer
/// @param image the destination image
void copyBufferToImage(const vk::Buffer& buffer, const vk::Image& image) const;
private:
ls::owned_ptr<VkCommandBuffer> commandBuffer;
};

View file

@ -4,6 +4,7 @@
#include "vulkan.hpp"
#include <cstddef>
#include <cstdint>
#include <vector>
#include <vulkan/vulkan_core.h>

View file

@ -12,10 +12,87 @@
#include <vulkan/vulkan_core.h>
namespace vk {
/// vulkan instance function pointers
struct VulkanInstanceFuncs {
PFN_vkDestroyInstance DestroyInstance;
PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
PFN_vkCreateDevice CreateDevice;
PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
};
using PhysicalDeviceSelector = const std::function<
VkPhysicalDevice(const std::vector<VkPhysicalDevice>&)
VkPhysicalDevice(
const VulkanInstanceFuncs&,
const std::vector<VkPhysicalDevice>&
)
>&;
/// vulkan device function pointers
struct VulkanDeviceFuncs {
PFN_vkGetDeviceQueue GetDeviceQueue;
PFN_vkDeviceWaitIdle DeviceWaitIdle;
PFN_vkCreateCommandPool CreateCommandPool;
PFN_vkDestroyCommandPool DestroyCommandPool;
PFN_vkCreateDescriptorPool CreateDescriptorPool;
PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
PFN_vkCreateBuffer CreateBuffer;
PFN_vkDestroyBuffer DestroyBuffer;
PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
PFN_vkAllocateMemory AllocateMemory;
PFN_vkFreeMemory FreeMemory;
PFN_vkBindBufferMemory BindBufferMemory;
PFN_vkMapMemory MapMemory;
PFN_vkUnmapMemory UnmapMemory;
PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
PFN_vkFreeCommandBuffers FreeCommandBuffers;
PFN_vkBeginCommandBuffer BeginCommandBuffer;
PFN_vkEndCommandBuffer EndCommandBuffer;
PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
PFN_vkCmdClearColorImage CmdClearColorImage;
PFN_vkCmdBindPipeline CmdBindPipeline;
PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
PFN_vkCmdDispatch CmdDispatch;
PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
PFN_vkQueueSubmit QueueSubmit;
PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
PFN_vkFreeDescriptorSets FreeDescriptorSets;
PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
PFN_vkCreateFence CreateFence;
PFN_vkDestroyFence DestroyFence;
PFN_vkResetFences ResetFences;
PFN_vkWaitForFences WaitForFences;
PFN_vkCreateImage CreateImage;
PFN_vkDestroyImage DestroyImage;
PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
PFN_vkBindImageMemory BindImageMemory;
PFN_vkCreateImageView CreateImageView;
PFN_vkDestroyImageView DestroyImageView;
PFN_vkCreateSampler CreateSampler;
PFN_vkDestroySampler DestroySampler;
PFN_vkCreateSemaphore CreateSemaphore;
PFN_vkDestroySemaphore DestroySemaphore;
PFN_vkCreateShaderModule CreateShaderModule;
PFN_vkDestroyShaderModule DestroyShaderModule;
PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
PFN_vkCreatePipelineLayout CreatePipelineLayout;
PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
PFN_vkCreateComputePipelines CreateComputePipelines;
PFN_vkDestroyPipeline DestroyPipeline;
PFN_vkSignalSemaphore SignalSemaphore;
PFN_vkWaitSemaphores WaitSemaphores;
// extension functions
PFN_vkGetMemoryFdKHR GetMemoryFdKHR;
PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR;
PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR;
};
/// vulkan version wrapper
class version {
public:
@ -73,14 +150,21 @@ namespace vk {
/// check if fp16 is supported
/// @return true if fp16 is supported
[[nodiscard]] bool supportsFP16() const { return this->fp16; }
/// get device-level function pointers
/// @return the device function pointers
[[nodiscard]] const auto& df() const { return this->device_funcs; }
private:
ls::owned_ptr<VkInstance> instance;
VulkanInstanceFuncs instance_funcs;
VkPhysicalDevice physdev;
uint32_t computeFamilyIdx;
bool fp16;
ls::owned_ptr<VkDevice> device;
VulkanDeviceFuncs device_funcs;
VkQueue computeQueue;
ls::owned_ptr<VkCommandPool> cmdPool;

View file

@ -25,14 +25,14 @@ namespace {
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
auto res = vkCreateBuffer(vk.dev(), &bufferInfo, nullptr, &handle);
auto res = vk.df().CreateBuffer(vk.dev(), &bufferInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateBuffer() failed");
return ls::owned_ptr<VkBuffer>(
new VkBuffer(handle),
[dev = vk.dev()](VkBuffer& buffer) {
vkDestroyBuffer(dev, buffer, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyBuffer](VkBuffer& buffer) {
defunc(dev, buffer, nullptr);
}
);
}
@ -41,7 +41,7 @@ namespace {
VkDeviceMemory handle{};
VkMemoryRequirements reqs{};
vkGetBufferMemoryRequirements(vk.dev(), buffer, &reqs);
vk.df().GetBufferMemoryRequirements(vk.dev(), buffer, &reqs);
auto mti = vk.findMemoryTypeIndex(
reqs.memoryTypeBits,
@ -55,18 +55,18 @@ namespace {
.allocationSize = reqs.size,
.memoryTypeIndex = *mti
};
auto res = vkAllocateMemory(vk.dev(), &memoryInfo, nullptr, &handle);
auto res = vk.df().AllocateMemory(vk.dev(), &memoryInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkAllocateMemory() failed");
res = vkBindBufferMemory(vk.dev(), buffer, handle, 0);
res = vk.df().BindBufferMemory(vk.dev(), buffer, handle, 0);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkBindBufferMemory() failed");
return ls::owned_ptr<VkDeviceMemory>(
new VkDeviceMemory(handle),
[dev = vk.dev()](VkDeviceMemory& memory) {
vkFreeMemory(dev, memory, nullptr);
[dev = vk.dev(), defunc = vk.df().FreeMemory](VkDeviceMemory& memory) {
defunc(dev, memory, nullptr);
}
);
}
@ -75,7 +75,7 @@ namespace {
VkDeviceMemory memory, const void* data, size_t size) {
void* buf{};
auto res = vkMapMemory(vk.dev(), memory, 0, size, 0, &buf);
auto res = vk.df().MapMemory(vk.dev(), memory, 0, size, 0, &buf);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkMapMemory() failed");
@ -85,7 +85,7 @@ namespace {
reinterpret_cast<uint8_t*>(buf)
);
vkUnmapMemory(vk.dev(), memory);
vk.df().UnmapMemory(vk.dev(), memory);
}
}

View file

@ -28,14 +28,16 @@ namespace {
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1
};
auto res = vkAllocateCommandBuffers(vk.dev(), &commandBufferInfo, &handle);
auto res = vk.df().AllocateCommandBuffers(vk.dev(), &commandBufferInfo, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkAllocateCommandBuffers() failed");
return ls::owned_ptr<VkCommandBuffer>(
new VkCommandBuffer(handle),
[dev = vk.dev(), pool = vk.cmdpool()](VkCommandBuffer& commandBufferModule) {
vkFreeCommandBuffers(dev, pool, 1, &commandBufferModule);
[dev = vk.dev(), pool = vk.cmdpool(), defunc = vk.df().FreeCommandBuffers](
VkCommandBuffer& commandBufferModule
) {
defunc(dev, pool, 1, &commandBufferModule);
}
);
}
@ -48,12 +50,13 @@ CommandBuffer::CommandBuffer(const vk::Vulkan& vk)
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
};
auto res = vkBeginCommandBuffer(*this->commandBuffer, &beginInfo);
auto res = vk.df().BeginCommandBuffer(*this->commandBuffer, &beginInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkBeginCommandBuffer() failed");
}
void CommandBuffer::prepareImage(const vk::Image& image,
void CommandBuffer::prepareImage(const vk::Vulkan& vk,
const vk::Image& image,
const std::optional<VkClearColorValue>& clearColor) const {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -68,7 +71,7 @@ void CommandBuffer::prepareImage(const vk::Image& image,
.layerCount = 1
}
};
vkCmdPipelineBarrier(*this->commandBuffer,
vk.df().CmdPipelineBarrier(*this->commandBuffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
@ -77,7 +80,7 @@ void CommandBuffer::prepareImage(const vk::Image& image,
);
if (clearColor.has_value()) {
vkCmdClearColorImage(*this->commandBuffer,
vk.df().CmdClearColorImage(*this->commandBuffer,
image.handle(),
VK_IMAGE_LAYOUT_GENERAL,
&clearColor.value(),
@ -86,11 +89,12 @@ void CommandBuffer::prepareImage(const vk::Image& image,
}
}
void CommandBuffer::dispatch(const vk::Shader& shader,
void CommandBuffer::dispatch(const vk::Vulkan& vk,
const vk::Shader& shader,
const vk::DescriptorSet& set,
const std::vector<vk::Barrier>& barriers,
uint32_t x, uint32_t y, uint32_t z) const {
vkCmdPipelineBarrier(*this->commandBuffer,
vk.df().CmdPipelineBarrier(*this->commandBuffer,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0,
@ -98,23 +102,65 @@ void CommandBuffer::dispatch(const vk::Shader& shader,
0, nullptr,
static_cast<uint32_t>(barriers.size()), barriers.data()
);
vkCmdBindPipeline(*this->commandBuffer,
vk.df().CmdBindPipeline(*this->commandBuffer,
VK_PIPELINE_BIND_POINT_COMPUTE,
shader.pipeline()
);
vkCmdBindDescriptorSets(*this->commandBuffer,
vk.df().CmdBindDescriptorSets(*this->commandBuffer,
VK_PIPELINE_BIND_POINT_COMPUTE,
shader.pipelinelayout(),
0, 1, &set.handle(),
0, nullptr
);
vkCmdDispatch(*this->commandBuffer, x, y, z);
vk.df().CmdDispatch(*this->commandBuffer, x, y, z);
}
void CommandBuffer::copyBufferToImage(const vk::Vulkan& vk,
const vk::Buffer& buffer, const vk::Image& image) const {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_NONE,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.image = image.handle(),
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1
}
};
vk.df().CmdPipelineBarrier(*this->commandBuffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
const VkBufferImageCopy region{
.bufferImageHeight = 0,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.layerCount = 1
},
.imageExtent = {
.width = image.getExtent().width,
.height = image.getExtent().height,
.depth = 1
}
};
vk.df().CmdCopyBufferToImage(*this->commandBuffer,
buffer.handle(), image.handle(),
VK_IMAGE_LAYOUT_GENERAL, 1, &region
);
}
void CommandBuffer::submit(const vk::Vulkan& vk,
const vk::TimelineSemaphore& waitSemaphore, uint64_t waitValue,
const vk::TimelineSemaphore& signalSemaphore, uint64_t signalValue) const {
auto res = vkEndCommandBuffer(*this->commandBuffer);
auto res = vk.df().EndCommandBuffer(*this->commandBuffer);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkEndCommandBuffer() failed");
@ -138,13 +184,13 @@ void CommandBuffer::submit(const vk::Vulkan& vk,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &signalSemaphore.handle()
};
res = vkQueueSubmit(vk.queue(), 1, &submitInfo, VK_NULL_HANDLE);
res = vk.df().QueueSubmit(vk.queue(), 1, &submitInfo, VK_NULL_HANDLE);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkQueueSubmit() failed");
}
void CommandBuffer::submit(const vk::Vulkan& vk) const {
auto res = vkEndCommandBuffer(*this->commandBuffer);
auto res = vk.df().EndCommandBuffer(*this->commandBuffer);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkEndCommandBuffer() failed");
@ -154,50 +200,10 @@ void CommandBuffer::submit(const vk::Vulkan& vk) const {
.pCommandBuffers = &*this->commandBuffer
};
const vk::Fence fence{vk};
res = vkQueueSubmit(vk.queue(), 1, &submitInfo, fence.handle());
res = vk.df().QueueSubmit(vk.queue(), 1, &submitInfo, fence.handle());
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkQueueSubmit() failed");
if (!fence.wait(vk))
throw ls::vulkan_error(VK_TIMEOUT, "Fence::wait() timed out");
}
void CommandBuffer::copyBufferToImage(const vk::Buffer& buffer, const vk::Image& image) const {
const VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_NONE,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.image = image.handle(),
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1
}
};
vkCmdPipelineBarrier(*this->commandBuffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
const VkBufferImageCopy region{
.bufferImageHeight = 0,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.layerCount = 1
},
.imageExtent = {
.width = image.getExtent().width,
.height = image.getExtent().height,
.depth = 1
}
};
vkCmdCopyBufferToImage(*this->commandBuffer,
buffer.handle(), image.handle(),
VK_IMAGE_LAYOUT_GENERAL, 1, &region
);
}

View file

@ -28,14 +28,16 @@ namespace {
.descriptorSetCount = 1,
.pSetLayouts = &layout
};
auto res = vkAllocateDescriptorSets(vk.dev(), &setInfo, &handle);
auto res = vk.df().AllocateDescriptorSets(vk.dev(), &setInfo, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkAllocateDescriptorSets() failed");
return ls::owned_ptr<VkDescriptorSet>(
new VkDescriptorSet(handle),
[dev = vk.dev(), pool = vk.descpool()](VkDescriptorSet& commandBufferModule) {
vkFreeDescriptorSets(dev, pool, 1, &commandBufferModule);
[dev = vk.dev(), pool = vk.descpool(), defunc = vk.df().FreeDescriptorSets](
VkDescriptorSet& commandBufferModule
) {
defunc(dev, pool, 1, &commandBufferModule);
}
);
}
@ -120,6 +122,6 @@ DescriptorSet::DescriptorSet(const vk::Vulkan& vk,
}))
});
vkUpdateDescriptorSets(vk.dev(),
vk.df().UpdateDescriptorSets(vk.dev(),
static_cast<uint32_t>(entries.size()), entries.data(), 0, nullptr);
}

View file

@ -17,14 +17,14 @@ namespace {
const VkFenceCreateInfo fenceInfo{
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
};
auto res = vkCreateFence(vk.dev(), &fenceInfo, nullptr, &handle);
auto res = vk.df().CreateFence(vk.dev(), &fenceInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateFence() failed");
return ls::owned_ptr<VkFence>(
new VkFence(handle),
[dev = vk.dev()](VkFence& fence) {
vkDestroyFence(dev, fence, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyFence](VkFence& fence) {
defunc(dev, fence, nullptr);
}
);
}
@ -35,14 +35,14 @@ Fence::Fence(const vk::Vulkan& vk)
void Fence::reset(const vk::Vulkan& vk) const {
VkFence fence = *this->fence;
auto res = vkResetFences(vk.dev(), 1, &fence);
auto res = vk.df().ResetFences(vk.dev(), 1, &fence);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkResetFences() failed");
}
bool Fence::wait(const vk::Vulkan& vk, uint64_t timeout) const {
VkFence fence = *this->fence;
auto res = vkWaitForFences(vk.dev(), 1, &fence, VK_TRUE, timeout);
auto res = vk.df().WaitForFences(vk.dev(), 1, &fence, VK_TRUE, timeout);
if (res != VK_SUCCESS && res != VK_TIMEOUT)
throw ls::vulkan_error(res, "vkWaitForFences() failed");

View file

@ -37,14 +37,14 @@ namespace {
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
auto res = vkCreateImage(vk.dev(), &imageInfo, nullptr, &handle);
auto res = vk.df().CreateImage(vk.dev(), &imageInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateImage() failed");
return ls::owned_ptr<VkImage>(
new VkImage(handle),
[dev = vk.dev()](VkImage& image) {
vkDestroyImage(dev, image, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyImage](VkImage& image) {
defunc(dev, image, nullptr);
}
);
}
@ -54,7 +54,7 @@ namespace {
VkDeviceMemory handle{};
VkMemoryRequirements reqs{};
vkGetImageMemoryRequirements(vk.dev(), image, &reqs);
vk.df().GetImageMemoryRequirements(vk.dev(), image, &reqs);
auto mti = vk.findMemoryTypeIndex(
reqs.memoryTypeBits,
@ -89,25 +89,22 @@ namespace {
.allocationSize = reqs.size,
.memoryTypeIndex = *mti
};
auto res = vkAllocateMemory(vk.dev(), &memoryInfo, nullptr, &handle);
auto res = vk.df().AllocateMemory(vk.dev(), &memoryInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkAllocateMemory() failed");
res = vkBindImageMemory(vk.dev(), image, handle, 0);
res = vk.df().BindImageMemory(vk.dev(), image, handle, 0);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkBindImageMemory() failed");
if (exportFd.has_value()) {
auto vkGetMemoryFdKHR = reinterpret_cast<PFN_vkGetMemoryFdKHR>(
vkGetDeviceProcAddr(vk.dev(), "vkGetMemoryFdKHR")); // TODO: cache
const VkMemoryGetFdInfoKHR fdInfo{
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
.memory = handle,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
};
int fd{};
res = vkGetMemoryFdKHR(vk.dev(), &fdInfo, &fd);
res = vk.df().GetMemoryFdKHR(vk.dev(), &fdInfo, &fd);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkGetMemoryFdKHR() failed");
**exportFd = fd;
@ -115,8 +112,8 @@ namespace {
return ls::owned_ptr<VkDeviceMemory>(
new VkDeviceMemory(handle),
[dev = vk.dev()](VkDeviceMemory& memory) {
vkFreeMemory(dev, memory, nullptr);
[dev = vk.dev(), defunc = vk.df().FreeMemory](VkDeviceMemory& memory) {
defunc(dev, memory, nullptr);
}
);
}
@ -138,14 +135,14 @@ namespace {
.layerCount = 1
}
};
auto res = vkCreateImageView(vk.dev(), &viewInfo, nullptr, &handle);
auto res = vk.df().CreateImageView(vk.dev(), &viewInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateImageView() failed");
return ls::owned_ptr<VkImageView>(
new VkImageView(handle),
[dev = vk.dev()](VkImageView& view) {
vkDestroyImageView(dev, view, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyImageView](VkImageView& view) {
defunc(dev, view, nullptr);
}
);
}

View file

@ -27,14 +27,14 @@ namespace {
white ? VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE
: VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK
};
auto res = vkCreateSampler(vk.dev(), &samplerInfo, nullptr, &handle);
auto res = vk.df().CreateSampler(vk.dev(), &samplerInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateSampler() failed");
return ls::owned_ptr<VkSampler>(
new VkSampler(handle),
[dev = vk.dev()](VkSampler& sampler) {
vkDestroySampler(dev, sampler, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroySampler](VkSampler& sampler) {
defunc(dev, sampler, nullptr);
}
);
}

View file

@ -22,30 +22,27 @@ namespace {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = fd.has_value() ? &exportInfo : nullptr
};
auto res = vkCreateSemaphore(vk.dev(), &semaphoreInfo, nullptr, &handle);
auto res = vk.df().CreateSemaphore(vk.dev(), &semaphoreInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateSemaphore() failed");
if (fd.has_value()) {
// import semaphore from fd
auto vkImportSemaphoreFdKHR = reinterpret_cast<PFN_vkImportSemaphoreFdKHR>(
vkGetDeviceProcAddr(vk.dev(), "vkImportSemaphoreFdKHR")); // TODO: cache
const VkImportSemaphoreFdInfoKHR importInfo{
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
.semaphore = handle,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
.fd = *fd // closes the fd
};
res = vkImportSemaphoreFdKHR(vk.dev(), &importInfo);
res = vk.df().ImportSemaphoreFdKHR(vk.dev(), &importInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkImportSemaphoreFdKHR() failed");
}
return ls::owned_ptr<VkSemaphore>(
new VkSemaphore(handle),
[dev = vk.dev()](VkSemaphore& semaphore) {
vkDestroySemaphore(dev, semaphore, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroySemaphore](VkSemaphore& semaphore) {
defunc(dev, semaphore, nullptr);
}
);
}

View file

@ -23,14 +23,14 @@ namespace {
.codeSize = data_len,
.pCode = reinterpret_cast<const uint32_t*>(data)
};
auto res = vkCreateShaderModule(vk.dev(), &shaderModuleInfo, nullptr, &handle);
auto res = vk.df().CreateShaderModule(vk.dev(), &shaderModuleInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateShaderModule() failed");
return ls::owned_ptr<VkShaderModule>(
new VkShaderModule(handle),
[dev = vk.dev()](VkShaderModule& shaderModule) {
vkDestroyShaderModule(dev, shaderModule, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyShaderModule](VkShaderModule& shaderModule) {
defunc(dev, shaderModule, nullptr);
}
);
}
@ -73,19 +73,21 @@ namespace {
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT
});
const VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo{
const VkDescriptorSetLayoutCreateInfo info{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = static_cast<uint32_t>(bindings.size()),
.pBindings = bindings.data()
};
auto res = vkCreateDescriptorSetLayout(vk.dev(), &descriptorLayoutInfo, nullptr, &handle);
auto res = vk.df().CreateDescriptorSetLayout(vk.dev(), &info, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateDescriptorSetLayout() failed");
return ls::owned_ptr<VkDescriptorSetLayout>(
new VkDescriptorSetLayout(handle),
[dev = vk.dev()](VkDescriptorSetLayout& layout) {
vkDestroyDescriptorSetLayout(dev, layout, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyDescriptorSetLayout](
VkDescriptorSetLayout& layout
) {
defunc(dev, layout, nullptr);
}
);
}
@ -100,14 +102,14 @@ namespace {
.setLayoutCount = 1,
.pSetLayouts = &descriptorLayout
};
auto res = vkCreatePipelineLayout(vk.dev(), &layoutInfo, nullptr, &handle);
auto res = vk.df().CreatePipelineLayout(vk.dev(), &layoutInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreatePipelineLayout() failed");
return ls::owned_ptr<VkPipelineLayout>(
new VkPipelineLayout(handle),
[dev = vk.dev()](VkPipelineLayout& layout) {
vkDestroyPipelineLayout(dev, layout, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyPipelineLayout](VkPipelineLayout& layout) {
defunc(dev, layout, nullptr);
}
);
}
@ -129,7 +131,7 @@ namespace {
.stage = shaderStageInfo,
.layout = pipelineLayout
};
auto res = vkCreateComputePipelines(vk.dev(),
auto res = vk.df().CreateComputePipelines(vk.dev(),
VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateComputePipelines() failed");
@ -138,8 +140,8 @@ namespace {
return ls::owned_ptr<VkPipeline>(
new VkPipeline(handle),
[dev = vk.dev()](VkPipeline& pipeline) {
vkDestroyPipeline(dev, pipeline, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroyPipeline](VkPipeline& pipeline) {
defunc(dev, pipeline, nullptr);
}
);
}

View file

@ -30,38 +30,32 @@ namespace {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = &typeInfo,
};
auto res = vkCreateSemaphore(vk.dev(), &semaphoreInfo, nullptr, &handle);
auto res = vk.df().CreateSemaphore(vk.dev(), &semaphoreInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateSemaphore() failed");
if (importFd.has_value()) {
// import semaphore from fd
auto vkImportSemaphoreFdKHR = reinterpret_cast<PFN_vkImportSemaphoreFdKHR>(
vkGetDeviceProcAddr(vk.dev(), "vkImportSemaphoreFdKHR")); // TODO: cache
const VkImportSemaphoreFdInfoKHR importInfo{
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
.semaphore = handle,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
.fd = *importFd // closes the fd
};
res = vkImportSemaphoreFdKHR(vk.dev(), &importInfo);
res = vk.df().ImportSemaphoreFdKHR(vk.dev(), &importInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkImportSemaphoreFdKHR() failed");
}
if (exportFd.has_value()) {
// export semaphore to fd
auto vkGetSemaphoreFdKHR = reinterpret_cast<PFN_vkGetSemaphoreFdKHR>(
vkGetDeviceProcAddr(vk.dev(), "vkGetSemaphoreFdKHR")); // TODO: cache
const VkSemaphoreGetFdInfoKHR getFdInfo{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
.semaphore = handle,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT
};
int fd{};
res = vkGetSemaphoreFdKHR(vk.dev(), &getFdInfo, &fd);
res = vk.df().GetSemaphoreFdKHR(vk.dev(), &getFdInfo, &fd);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkGetSemaphoreFdKHR() failed");
@ -70,8 +64,8 @@ namespace {
return ls::owned_ptr<VkSemaphore>(
new VkSemaphore(handle),
[dev = vk.dev()](VkSemaphore& semaphore) {
vkDestroySemaphore(dev, semaphore, nullptr);
[dev = vk.dev(), defunc = vk.df().DestroySemaphore](VkSemaphore& semaphore) {
defunc(dev, semaphore, nullptr);
}
);
}
@ -87,7 +81,7 @@ void TimelineSemaphore::signal(const vk::Vulkan& vk, uint64_t value) const {
.semaphore = *this->semaphore,
.value = value
};
auto res = vkSignalSemaphore(vk.dev(), &signalInfo);
auto res = vk.df().SignalSemaphore(vk.dev(), &signalInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkSignalSemaphore() failed");
}
@ -100,7 +94,7 @@ bool TimelineSemaphore::wait(const vk::Vulkan& vk, uint64_t value, uint64_t time
.pSemaphores = &semaphore,
.pValues = &value
};
auto res = vkWaitSemaphores(vk.dev(), &waitInfo, timeout);
auto res = vk.df().WaitSemaphores(vk.dev(), &waitInfo, timeout);
if (res != VK_SUCCESS && res != VK_TIMEOUT)
throw ls::vulkan_error(res, "vkWaitSemaphores() failed");

View file

@ -9,24 +9,66 @@
#include <string>
#include <vector>
#include <dlfcn.h>
#include <vulkan/vulkan_core.h>
using namespace vk;
namespace {
/// load libvulkan.so.1 and return its handle
void* get_vulkan_handle() {
static void* handle{nullptr}; // NOLINT
if (handle) return handle;
handle = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL);
if (!handle)
throw ls::vulkan_error("failed to load libvulkan.so.1");
return handle;
}
/// get the main proc addr function
PFN_vkGetInstanceProcAddr get_mpa() {
static PFN_vkGetInstanceProcAddr mpa{nullptr}; // NOLINT
if (mpa) return mpa;
mpa = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
dlsym(get_vulkan_handle(), "vkGetInstanceProcAddr"));
if (!mpa)
throw ls::vulkan_error("failed to get vkGetInstanceProcAddr symbol");
return mpa;
}
}
namespace {
template<typename T>
T ipa(PFN_vkGetInstanceProcAddr mpa, VkInstance instance, const char* name) {
T func = reinterpret_cast<T>(
mpa(instance, name));
if (!func)
throw ls::vulkan_error("failed to get instance proc addr for " + std::string(name));
return func;
}
/// create a vulkan instance
ls::owned_ptr<VkInstance> createInstance(
const std::string& appName, version appVersion,
const std::string& engineName, version engineVersion) {
VkInstance handle{};
auto vkCreateInstance =
ipa<PFN_vkCreateInstance>(get_mpa(), nullptr, "vkCreateInstance");
if (!vkCreateInstance)
throw ls::vulkan_error("failed to get vkCreateInstance symbol");
const VkApplicationInfo appInfo{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = appName.c_str(),
.applicationVersion = appVersion.into(),
.pEngineName = engineName.c_str(),
.engineVersion = engineVersion.into(),
.apiVersion = VK_API_VERSION_1_2 // seems Vulkan 1.2 is supported on all Vulkan-capable GPUs
.apiVersion = VK_API_VERSION_1_2 // seems 1.2 is supported on all Vulkan-capable GPUs
};
const VkInstanceCreateInfo instanceInfo{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
@ -36,29 +78,55 @@ namespace {
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateInstance() failed");
auto defunc =
ipa<PFN_vkDestroyInstance>(get_mpa(), handle, "vkDestroyInstance");
if (!defunc)
throw ls::vulkan_error("failed to get vkDestroyInstance symbol");
return ls::owned_ptr<VkInstance>(
new VkInstance(handle),
[](VkInstance& instance) {
vkDestroyInstance(instance, nullptr);
[defunc](VkInstance& instance) {
defunc(instance, nullptr);
}
);
}
/// initialize vulkan instance function pointers
VulkanInstanceFuncs initVulkanInstanceFuncs(VkInstance i) {
const auto& mpa = get_mpa();
return {
.DestroyInstance = ipa<PFN_vkDestroyInstance>(mpa, i, "vkDestroyInstance"),
.EnumeratePhysicalDevices = ipa<PFN_vkEnumeratePhysicalDevices>(mpa, i,
"vkEnumeratePhysicalDevices"),
.GetPhysicalDeviceProperties = ipa<PFN_vkGetPhysicalDeviceProperties>(mpa, i,
"vkGetPhysicalDeviceProperties"),
.GetPhysicalDeviceQueueFamilyProperties =
ipa<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(mpa, i,
"vkGetPhysicalDeviceQueueFamilyProperties"),
.GetPhysicalDeviceFeatures2 = ipa<PFN_vkGetPhysicalDeviceFeatures2>(mpa, i,
"vkGetPhysicalDeviceFeatures2"),
.GetPhysicalDeviceMemoryProperties = ipa<PFN_vkGetPhysicalDeviceMemoryProperties>(mpa, i,
"vkGetPhysicalDeviceMemoryProperties"),
.CreateDevice = ipa<PFN_vkCreateDevice>(mpa, i, "vkCreateDevice"),
.GetDeviceProcAddr = ipa<PFN_vkGetDeviceProcAddr>(mpa, i, "vkGetDeviceProcAddr"),
};
}
/// filter for a physical device
VkPhysicalDevice findPhysicalDevice(
VkPhysicalDevice findPhysicalDevice(const VulkanInstanceFuncs& fi,
VkInstance instance,
PhysicalDeviceSelector filter) {
uint32_t phydevCount{};
auto res = vkEnumeratePhysicalDevices(instance, &phydevCount, nullptr);
auto res = fi.EnumeratePhysicalDevices(instance, &phydevCount, nullptr);
if (res != VK_SUCCESS || phydevCount == 0)
throw ls::vulkan_error(res, "vkEnumeratePhysicalDevices() failed");
std::vector<VkPhysicalDevice> phydevs(phydevCount);
res = vkEnumeratePhysicalDevices(instance, &phydevCount, phydevs.data());
res = fi.EnumeratePhysicalDevices(instance, &phydevCount, phydevs.data());
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkEnumeratePhysicalDevices() failed");
VkPhysicalDevice selected = filter(phydevs);
VkPhysicalDevice selected = filter(fi, phydevs);
if (!selected)
throw ls::vulkan_error("no suitable physical device found");
@ -66,12 +134,13 @@ namespace {
}
/// find the queue family index with given flags
uint32_t findQFI(VkPhysicalDevice physdev, VkQueueFlags flags) {
uint32_t findQFI(const VulkanInstanceFuncs& fi,
VkPhysicalDevice physdev, VkQueueFlags flags) {
uint32_t queueCount{};
vkGetPhysicalDeviceQueueFamilyProperties(physdev, &queueCount, nullptr);
fi.GetPhysicalDeviceQueueFamilyProperties(physdev, &queueCount, nullptr);
std::vector<VkQueueFamilyProperties> queues(queueCount);
vkGetPhysicalDeviceQueueFamilyProperties(physdev, &queueCount, queues.data());
fi.GetPhysicalDeviceQueueFamilyProperties(physdev, &queueCount, queues.data());
for (uint32_t i = 0; i < queueCount; ++i) {
if ((queues[i].queueFlags & flags) == flags)
@ -82,7 +151,7 @@ namespace {
}
/// check for fp16 support
bool checkFP16(VkPhysicalDevice physdev) {
bool checkFP16(const VulkanInstanceFuncs& fi, VkPhysicalDevice physdev) {
VkPhysicalDeviceVulkan12Features supportedFeaturesVulkan12{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES
};
@ -90,12 +159,22 @@ namespace {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &supportedFeaturesVulkan12
};
vkGetPhysicalDeviceFeatures2(physdev, &supportedFeatures);
fi.GetPhysicalDeviceFeatures2(physdev, &supportedFeatures);
return supportedFeaturesVulkan12.shaderFloat16 == VK_TRUE;
}
template<typename T>
T dpa(const VulkanInstanceFuncs& funcs, VkDevice device, const char* name) {
T func = reinterpret_cast<T>(
funcs.GetDeviceProcAddr(device, name));
if (!func)
throw ls::vulkan_error("failed to get device proc addr for " + std::string(name));
return func;
}
/// create a logical device
ls::owned_ptr<VkDevice> createLogicalDevice(VkPhysicalDevice physdev, uint32_t cfi, bool fp16) {
ls::owned_ptr<VkDevice> createLogicalDevice(const VulkanInstanceFuncs& fi,
VkPhysicalDevice physdev, uint32_t cfi, bool fp16) {
VkDevice handle{};
const float queuePriority{1.0F}; // highest priority
@ -124,48 +203,124 @@ namespace {
.enabledExtensionCount = static_cast<uint32_t>(requestedExtensions.size()),
.ppEnabledExtensionNames = requestedExtensions.data()
};
auto res = vkCreateDevice(physdev, &deviceInfo, nullptr, &handle);
auto res = fi.CreateDevice(physdev, &deviceInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateDevice() failed");
auto defunc =
dpa<PFN_vkDestroyDevice>(fi, handle, "vkDestroyDevice");
if (!defunc)
throw ls::vulkan_error("failed to get vkDestroyDevice symbol");
return ls::owned_ptr<VkDevice>(
new VkDevice(handle),
[](VkDevice& device) {
vkDestroyDevice(device, nullptr);
[defunc](VkDevice& device) {
defunc(device, nullptr);
}
);
}
/// initialize vulkan device function pointers
VulkanDeviceFuncs initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevice d) {
return {
.GetDeviceQueue = dpa<PFN_vkGetDeviceQueue>(f, d, "vkGetDeviceQueue"),
.DeviceWaitIdle = dpa<PFN_vkDeviceWaitIdle>(f, d, "vkDeviceWaitIdle"),
.CreateCommandPool = dpa<PFN_vkCreateCommandPool>(f, d, "vkCreateCommandPool"),
.DestroyCommandPool = dpa<PFN_vkDestroyCommandPool>(f, d, "vkDestroyCommandPool"),
.CreateDescriptorPool = dpa<PFN_vkCreateDescriptorPool>(f, d, "vkCreateDescriptorPool"),
.DestroyDescriptorPool = dpa<PFN_vkDestroyDescriptorPool>(f, d, "vkDestroyDescriptorPool"),
.CreateBuffer = dpa<PFN_vkCreateBuffer>(f, d, "vkCreateBuffer"),
.DestroyBuffer = dpa<PFN_vkDestroyBuffer>(f, d, "vkDestroyBuffer"),
.GetBufferMemoryRequirements = dpa<PFN_vkGetBufferMemoryRequirements>(f, d,
"vkGetBufferMemoryRequirements"),
.AllocateMemory = dpa<PFN_vkAllocateMemory>(f, d, "vkAllocateMemory"),
.FreeMemory = dpa<PFN_vkFreeMemory>(f, d, "vkFreeMemory"),
.BindBufferMemory = dpa<PFN_vkBindBufferMemory>(f, d, "vkBindBufferMemory"),
.MapMemory = dpa<PFN_vkMapMemory>(f, d, "vkMapMemory"),
.UnmapMemory = dpa<PFN_vkUnmapMemory>(f, d, "vkUnmapMemory"),
.AllocateCommandBuffers = dpa<PFN_vkAllocateCommandBuffers>(f, d,
"vkAllocateCommandBuffers"),
.FreeCommandBuffers = dpa<PFN_vkFreeCommandBuffers>(f, d, "vkFreeCommandBuffers"),
.BeginCommandBuffer = dpa<PFN_vkBeginCommandBuffer>(f, d, "vkBeginCommandBuffer"),
.EndCommandBuffer = dpa<PFN_vkEndCommandBuffer>(f, d, "vkEndCommandBuffer"),
.CmdPipelineBarrier = dpa<PFN_vkCmdPipelineBarrier>(f, d, "vkCmdPipelineBarrier"),
.CmdClearColorImage = dpa<PFN_vkCmdClearColorImage>(f, d, "vkCmdClearColorImage"),
.CmdBindPipeline = dpa<PFN_vkCmdBindPipeline>(f, d, "vkCmdBindPipeline"),
.CmdBindDescriptorSets = dpa<PFN_vkCmdBindDescriptorSets>(f, d, "vkCmdBindDescriptorSets"),
.CmdDispatch = dpa<PFN_vkCmdDispatch>(f, d, "vkCmdDispatch"),
.CmdCopyBufferToImage = dpa<PFN_vkCmdCopyBufferToImage>(f, d, "vkCmdCopyBufferToImage"),
.QueueSubmit = dpa<PFN_vkQueueSubmit>(f, d, "vkQueueSubmit"),
.AllocateDescriptorSets = dpa<PFN_vkAllocateDescriptorSets>(f, d,
"vkAllocateDescriptorSets"),
.FreeDescriptorSets = dpa<PFN_vkFreeDescriptorSets>(f, d, "vkFreeDescriptorSets"),
.UpdateDescriptorSets = dpa<PFN_vkUpdateDescriptorSets>(f, d, "vkUpdateDescriptorSets"),
.CreateFence = dpa<PFN_vkCreateFence>(f, d, "vkCreateFence"),
.DestroyFence = dpa<PFN_vkDestroyFence>(f, d, "vkDestroyFence"),
.ResetFences = dpa<PFN_vkResetFences>(f, d, "vkResetFences"),
.WaitForFences = dpa<PFN_vkWaitForFences>(f, d, "vkWaitForFences"),
.CreateImage = dpa<PFN_vkCreateImage>(f, d, "vkCreateImage"),
.DestroyImage = dpa<PFN_vkDestroyImage>(f, d, "vkDestroyImage"),
.GetImageMemoryRequirements = dpa<PFN_vkGetImageMemoryRequirements>(f, d,
"vkGetImageMemoryRequirements"),
.BindImageMemory = dpa<PFN_vkBindImageMemory>(f, d, "vkBindImageMemory"),
.CreateImageView = dpa<PFN_vkCreateImageView>(f, d, "vkCreateImageView"),
.DestroyImageView = dpa<PFN_vkDestroyImageView>(f, d, "vkDestroyImageView"),
.CreateSampler = dpa<PFN_vkCreateSampler>(f, d, "vkCreateSampler"),
.DestroySampler = dpa<PFN_vkDestroySampler>(f, d, "vkDestroySampler"),
.CreateSemaphore = dpa<PFN_vkCreateSemaphore>(f, d, "vkCreateSemaphore"),
.DestroySemaphore = dpa<PFN_vkDestroySemaphore>(f, d, "vkDestroySemaphore"),
.CreateShaderModule = dpa<PFN_vkCreateShaderModule>(f, d, "vkCreateShaderModule"),
.DestroyShaderModule = dpa<PFN_vkDestroyShaderModule>(f, d, "vkDestroyShaderModule"),
.CreateDescriptorSetLayout = dpa<PFN_vkCreateDescriptorSetLayout>(f, d,
"vkCreateDescriptorSetLayout"),
.DestroyDescriptorSetLayout = dpa<PFN_vkDestroyDescriptorSetLayout>(f, d,
"vkDestroyDescriptorSetLayout"),
.CreatePipelineLayout = dpa<PFN_vkCreatePipelineLayout>(f, d, "vkCreatePipelineLayout"),
.DestroyPipelineLayout = dpa<PFN_vkDestroyPipelineLayout>(f, d, "vkDestroyPipelineLayout"),
.CreateComputePipelines = dpa<PFN_vkCreateComputePipelines>(f, d,
"vkCreateComputePipelines"),
.DestroyPipeline = dpa<PFN_vkDestroyPipeline>(f, d, "vkDestroyPipeline"),
.SignalSemaphore = dpa<PFN_vkSignalSemaphore>(f, d, "vkSignalSemaphore"),
.WaitSemaphores = dpa<PFN_vkWaitSemaphores>(f, d, "vkWaitSemaphores"),
.GetMemoryFdKHR = dpa<PFN_vkGetMemoryFdKHR>(f, d, "vkGetMemoryFdKHR"),
.ImportSemaphoreFdKHR = dpa<PFN_vkImportSemaphoreFdKHR>(f, d, "vkImportSemaphoreFdKHR"),
.GetSemaphoreFdKHR = dpa<PFN_vkGetSemaphoreFdKHR>(f, d, "vkGetSemaphoreFdKHR"),
};
}
/// get a queue from the logical device
VkQueue getQueue(VkDevice device, uint32_t cfi) {
VkQueue getQueue(const VulkanDeviceFuncs& fd,
VkDevice device, uint32_t cfi) {
VkQueue queue{};
vkGetDeviceQueue(device, cfi, 0, &queue);
fd.GetDeviceQueue(device, cfi, 0, &queue);
return queue;
}
/// create a command pool
ls::owned_ptr<VkCommandPool> createCommandPool(VkDevice device, uint32_t cfi) {
ls::owned_ptr<VkCommandPool> createCommandPool(const VulkanDeviceFuncs& fd,
VkDevice device, uint32_t cfi) {
VkCommandPool handle{};
const VkCommandPoolCreateInfo cmdpoolInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.queueFamilyIndex = cfi
};
auto res = vkCreateCommandPool(device, &cmdpoolInfo, nullptr, &handle);
auto res = fd.CreateCommandPool(device, &cmdpoolInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateCommandPool() failed");
return ls::owned_ptr<VkCommandPool>(
new VkCommandPool(handle),
[dev = device](VkCommandPool& pool) {
vkDestroyCommandPool(dev, pool, nullptr);
[dev = device, defunc = fd.DestroyCommandPool](VkCommandPool& pool) {
defunc(dev, pool, nullptr);
}
);
}
/// create a descriptor pool
ls::owned_ptr<VkDescriptorPool> createDescriptorPool(VkDevice device) {
ls::owned_ptr<VkDescriptorPool> createDescriptorPool(const VulkanDeviceFuncs& fd,
VkDevice device) {
VkDescriptorPool handle{};
const std::array<VkDescriptorPoolSize, 4> poolCounts{{ // FIXME: arbitrary limits
@ -181,14 +336,14 @@ namespace {
.poolSizeCount = static_cast<uint32_t>(poolCounts.size()),
.pPoolSizes = poolCounts.data()
};
auto res = vkCreateDescriptorPool(device, &descpoolInfo, nullptr, &handle);
auto res = fd.CreateDescriptorPool(device, &descpoolInfo, nullptr, &handle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkCreateDescriptorPool() failed");
return ls::owned_ptr<VkDescriptorPool>(
new VkDescriptorPool(handle),
[dev = device](VkDescriptorPool& pool) {
vkDestroyDescriptorPool(dev, pool, nullptr);
[dev = device, defunc = fd.DestroyDescriptorPool](VkDescriptorPool& pool) {
defunc(dev, pool, nullptr);
}
);
}
@ -201,23 +356,28 @@ Vulkan::Vulkan(const std::string& appName, version appVersion,
appName, appVersion,
engineName, engineVersion
)),
physdev(findPhysicalDevice(
instance_funcs(initVulkanInstanceFuncs(*this->instance)),
physdev(findPhysicalDevice(this->instance_funcs,
*this->instance,
selectPhysicalDevice
)),
computeFamilyIdx(findQFI(this->physdev, VK_QUEUE_COMPUTE_BIT)),
fp16(checkFP16(this->physdev)),
device(createLogicalDevice(
computeFamilyIdx(findQFI(this->instance_funcs, this->physdev, VK_QUEUE_COMPUTE_BIT)),
fp16(checkFP16(this->instance_funcs, this->physdev)),
device(createLogicalDevice(this->instance_funcs,
this->physdev,
this->computeFamilyIdx,
this->fp16
)),
computeQueue(getQueue(*this->device, this->computeFamilyIdx)),
cmdPool(createCommandPool(
device_funcs(initVulkanDeviceFuncs(
this->instance_funcs,
*this->device
)),
computeQueue(getQueue(this->device_funcs, *this->device, this->computeFamilyIdx)),
cmdPool(createCommandPool(this->device_funcs,
*this->device,
this->computeFamilyIdx
)),
descPool(createDescriptorPool(
descPool(createDescriptorPool(this->device_funcs,
*this->device
)) {
}
@ -229,7 +389,7 @@ std::optional<uint32_t> Vulkan::findMemoryTypeIndex(
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkPhysicalDeviceMemoryProperties props;
vkGetPhysicalDeviceMemoryProperties(this->physdev, &props);
this->instance_funcs.GetPhysicalDeviceMemoryProperties(this->physdev, &props);
std::array<VkMemoryType, 32> memTypes = std::to_array(props.memoryTypes);
for (uint32_t i = 0; i < props.memoryTypeCount; ++i)

View file

@ -60,7 +60,7 @@ namespace {
VK_BUFFER_USAGE_TRANSFER_SRC_BIT};
const vk::CommandBuffer cmdbuf{vk};
cmdbuf.copyBufferToImage(stagingbuf, image);
cmdbuf.copyBufferToImage(vk, stagingbuf, image);
const vk::TimelineSemaphore sema{vk, 0};
cmdbuf.submit(vk, sema, 1, sema, 2);
@ -77,7 +77,8 @@ int main() {
const vk::Vulkan vk{
"lsfg-vk-debug", vk::version{1, 1, 0},
"lsfg-vk-debug-engine", vk::version{1, 0, 0},
[](const std::vector<VkPhysicalDevice>& devices) {
[](const vk::VulkanInstanceFuncs,
const std::vector<VkPhysicalDevice>& devices) {
return devices.front();
}
};