refactor: add useful helpers for images

This commit is contained in:
PancakeTAS 2025-09-01 19:53:41 +02:00
parent 438458a575
commit 29ee02f080
No known key found for this signature in database
10 changed files with 238 additions and 12 deletions

View file

@ -64,3 +64,32 @@ void Mipmaps::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount) {
this->descriptorSets.at(frameCount % 2).bind(buf, this->pipeline);
buf.dispatch(threadsX, threadsY, 1);
}
// modern writing style
/*
Mipmaps::Mipmap(Vulkan& vk, TemporalImage in) : in(in) {
const auto flow = Utils::fdiv2D(images[0].getExtent(), vk.flowScale);
this->out = MipmappedImage(vk, flow, 7, VK_FORMAT_R8_UNORM);
this->buffer = vk.resources.getBuffer(vk.device);
this->sampler = vk.resources.getSampler(vk.device);
this->shader = ShaderBuilder(vk, "mipmaps")
.withBuffer(this->buffer)
.withSampler(this->sampler)
.withInput(this->in, ShaderBuilder::CURRENT)
.withOutput(this->out, ShaderBuilder::MIPMAP_FLAT)
.build();
void Mipmaps::prepare(const CommandBuffer& buf) {
this->in.prepareAll(buf);
this->out.prepareAll(buf);
}
void Mipmaps::Dispatch() {
const auto flow = this->out.getExtent(0);
const uint32_t threadsX = (flow.width + 63) >> 6;
const uint32_t threadsY = (flow.height + 63) >> 6;
this->shader.dispatch(buf, threadsX, threadsY);
}
*/

View file

@ -15,8 +15,10 @@ project(lsfg-vk-framegen
file(GLOB SOURCES
"src/vk/core/*.cpp"
"src/vk/helper/*.cpp"
"src/vk/*.cpp"
"src/*.cpp"
"src/thirdparty/*.c"
)
add_library(lsfg-vk-framegen STATIC ${SOURCES})
@ -50,8 +52,6 @@ if(LSFGVK_EXCESS_DEBUG)
-Wno-switch-enum # ignore missing cases
-Wno-switch-default # ignore missing default
-Wno-padded # ignore automatic padding
-Wno-exit-time-destructors # allow globals
-Wno-global-constructors # allow globals
-Wno-cast-function-type-strict # for vulkan
)

View file

@ -0,0 +1,54 @@
#pragma once
#include "vk/core/device.hpp"
#include "vk/core/image.hpp"
#include <vulkan/vulkan_core.h>
#include <algorithm>
#include <cstddef>
#include <vector>
namespace VK::Helper {
///
/// Helper class for a list of images with similar properties.
///
class ImageGroup {
public:
ImageGroup() noexcept = default;
///
/// Create an image group.
///
/// @param device Vulkan device.
/// @param extent Extent of the base level.
/// @param count Number of images (must be at least 1).
/// @param format Image format.
///
/// @throws VK::vulkan_error if object creation fails.
///
ImageGroup(const Core::Device& device, VkExtent2D extent,
size_t count, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM);
/// Get the number of images
[[nodiscard]] auto count() const noexcept { return this->images.size(); }
/// Get a specific image.
[[nodiscard]] const auto& get(size_t i) const { return this->images.at(i); }
/// Get all images.
[[nodiscard]] const auto& into() const noexcept { return this->images; }
/// Get a subgroup of images
[[nodiscard]] std::vector<Core::Image> subGroup(size_t start, size_t length) const {
if (start + length > this->count())
throw std::out_of_range("Sub group range out of bounds");
std::vector<Core::Image> subgroup(length);
std::copy_n(&this->images.at(start), length, subgroup.data());
return subgroup;
}
private:
std::vector<Core::Image> images;
};
}

View file

@ -0,0 +1,43 @@
#pragma once
#include "vk/core/device.hpp"
#include "vk/core/image.hpp"
#include <vulkan/vulkan_core.h>
#include <cstddef>
#include <vector>
namespace VK::Helper {
///
/// Helper class for a list of mipmapped images.
///
class MipmappedImage {
public:
MipmappedImage() noexcept = default;
///
/// Create a mipmappped image.
///
/// @param device Vulkan device.
/// @param extent Extent of the base level.
/// @param levels Number of mip levels (must be at least 1).
/// @param format Image format.
///
/// @throws VK::vulkan_error if object creation fails.
///
MipmappedImage(const Core::Device& device, VkExtent2D extent,
size_t levels, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM);
/// Get the number of mip levels.
[[nodiscard]] auto levels() const noexcept { return this->images.size(); }
/// Get a specific mip level image.
[[nodiscard]] const auto& get(size_t i) const { return this->images.at(i); }
/// Get all mip level images.
[[nodiscard]] const auto& into() const noexcept { return this->images; }
private:
std::vector<Core::Image> images;
};
}

View file

@ -0,0 +1,53 @@
#pragma once
#include "vk/core/device.hpp"
#include "vk/core/image.hpp"
#include <vulkan/vulkan_core.h>
#include <cstddef>
#include <vector>
namespace VK::Helper {
///
/// Helper class for a list of temporal images.
///
class TemporalImage {
public:
TemporalImage() noexcept = default;
///
/// Create a temporal image.
///
/// @param device Vulkan device.
/// @param extent Extent of the images.
/// @param count Amount of images (must be at least 1).
/// @param format Image format.
///
/// @throws VK::vulkan_error if object creation fails.
///
TemporalImage(const Core::Device& device, VkExtent2D extent,
size_t count, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM);
///
/// Create a temporal image based on existing images.
///
/// @param images Vector of existing images.
///
TemporalImage(std::vector<Core::Image> images)
: images(std::move(images)) {}
/// Get the number of images.
[[nodiscard]] auto count() const noexcept { return this->images.size(); }
/// Get a specific image.
[[nodiscard]] const auto& get(size_t i) const { return this->images.at(i); }
/// Get the image based on frame index.
[[nodiscard]] const auto& at(size_t f) const { return this->images.at(f % this->count()); }
/// Get all images.
[[nodiscard]] const auto& into() const noexcept { return this->images; }
private:
std::vector<Core::Image> images;
};
}

View file

@ -15,7 +15,7 @@
using namespace VK::Core;
const std::vector<const char*> requiredExtensions = {
const std::array<const char*, 3> requiredExtensions = {
"VK_KHR_external_memory_fd",
"VK_KHR_external_semaphore_fd",
"VK_EXT_robustness2"

View file

@ -4,16 +4,10 @@
#include "vk/core/instance.hpp"
#include "vk/exception.hpp"
#include <cstdint>
#include <memory>
#include <vector>
using namespace VK::Core;
const std::vector<const char*> requiredExtensions = {
// empty, for now :3
};
Instance::Instance() {
volkInitialize();
@ -28,9 +22,7 @@ Instance::Instance() {
};
const VkInstanceCreateInfo createInfo{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
.ppEnabledExtensionNames = requiredExtensions.data()
.pApplicationInfo = &appInfo
};
VkInstance instanceHandle{};
auto res = vkCreateInstance(&createInfo, nullptr, &instanceHandle);

View file

@ -0,0 +1,17 @@
#include <volk.h>
#include <vulkan/vulkan_core.h>
#include "vk/helper/image_group.hpp"
#include "vk/core/device.hpp"
#include <cstddef>
#include <vector>
using namespace VK::Helper;
ImageGroup::ImageGroup(const Core::Device& device, VkExtent2D extent,
size_t count, VkFormat format) {
this->images.reserve(count);
for (size_t i = 0; i < count; i++)
this->images.emplace_back(device, extent, format);
}

View file

@ -0,0 +1,21 @@
#include <volk.h>
#include <vulkan/vulkan_core.h>
#include "vk/helper/mipmapped_image.hpp"
#include "vk/core/device.hpp"
#include <cstddef>
#include <vector>
using namespace VK::Helper;
MipmappedImage::MipmappedImage(const Core::Device& device, VkExtent2D extent,
size_t levels, VkFormat format) {
this->images.reserve(levels);
for (size_t i = 0; i < levels; i++)
this->images.emplace_back(
device,
VkExtent2D { extent.width >> i, extent.height >> i },
format
);
}

View file

@ -0,0 +1,17 @@
#include <volk.h>
#include <vulkan/vulkan_core.h>
#include "vk/helper/temporal_image.hpp"
#include "vk/core/device.hpp"
#include <cstddef>
#include <vector>
using namespace VK::Helper;
TemporalImage::TemporalImage(const Core::Device& device, VkExtent2D extent,
size_t count, VkFormat format) {
this->images.reserve(count);
for (size_t i = 0; i < count; i++)
this->images.emplace_back(device, extent, format);
}