mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-03-25 20:51:36 +00:00
test(dualgpu): Create separate image for DMA-BUFs
This, again, is a temporary change just for messing around
This commit is contained in:
parent
d9fcbcd10e
commit
7e07c4ba3a
18 changed files with 679 additions and 36 deletions
|
|
@ -52,6 +52,13 @@ namespace lsfgvk::backend {
|
|||
const std::optional<std::string>& pci // (bus:slot.func) if available, no padded zeros
|
||||
)>;
|
||||
|
||||
/// Helper struct for importing DMA-BUF images
|
||||
struct DmaBufFD {
|
||||
int fd;
|
||||
uint64_t modifier;
|
||||
std::vector<std::pair<uint64_t, uint64_t>> layouts; // (offset, pitch) per plane
|
||||
};
|
||||
|
||||
///
|
||||
/// Main entry point of the library
|
||||
///
|
||||
|
|
@ -90,8 +97,8 @@ namespace lsfgvk::backend {
|
|||
/// @throws backend::error on failure
|
||||
///
|
||||
Context& openContext(
|
||||
std::pair<int, int> sourceFds,
|
||||
const std::vector<int>& destFds,
|
||||
const std::pair<DmaBufFD, DmaBufFD>& sourceFds,
|
||||
const std::vector<DmaBufFD>& destFds,
|
||||
uint32_t width, uint32_t height,
|
||||
bool hdr, float flow, bool perf
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/sampler.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shader.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -35,6 +36,21 @@ ManagedShaderBuilder& ManagedShaderBuilder::sampleds(
|
|||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::sampled(const vk::SharedImage& image) {
|
||||
this->sampledImagesSh.push_back(std::ref(image));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::sampleds(
|
||||
const std::vector<vk::SharedImage>& images,
|
||||
size_t offset, size_t count) {
|
||||
if (count == 0 || offset + count > images.size())
|
||||
count = images.size() - offset;
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
this->sampledImagesSh.push_back(std::ref(images[offset + i]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::storage(const vk::Image& image) {
|
||||
this->storageImages.push_back(std::ref(image));
|
||||
|
|
@ -52,6 +68,22 @@ ManagedShaderBuilder& ManagedShaderBuilder::storages(
|
|||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::storage(const vk::SharedImage& image) {
|
||||
this->storageImagesSh.push_back(std::ref(image));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::storages(
|
||||
const std::vector<vk::SharedImage>& images,
|
||||
size_t offset, size_t count) {
|
||||
if (count == 0 || offset + count > images.size())
|
||||
count = images.size() - offset;
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
this->storageImagesSh.push_back(std::ref(images[offset + i]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ManagedShaderBuilder& ManagedShaderBuilder::sampler(const vk::Sampler& sampler) {
|
||||
this->imageSamplers.push_back(std::ref(sampler));
|
||||
return *this;
|
||||
|
|
@ -72,8 +104,27 @@ ManagedShaderBuilder& ManagedShaderBuilder::buffer(const vk::Buffer& buffer) {
|
|||
ManagedShader ManagedShaderBuilder::build(const vk::Vulkan& vk,
|
||||
const vk::DescriptorPool& pool, const vk::Shader& shader) const {
|
||||
std::vector<vk::Barrier> barriers;
|
||||
barriers.reserve(this->storageImages.size() + this->sampledImages.size());
|
||||
barriers.reserve(
|
||||
this->storageImages.size() + this->sampledImages.size()
|
||||
+ this->storageImagesSh.size() + this->sampledImagesSh.size()
|
||||
);
|
||||
|
||||
for (const auto& img : this->sampledImagesSh)
|
||||
barriers.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = img.get().handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
});
|
||||
for (const auto& img : this->sampledImages)
|
||||
barriers.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
|
|
@ -90,6 +141,22 @@ ManagedShader ManagedShaderBuilder::build(const vk::Vulkan& vk,
|
|||
.layerCount = 1
|
||||
}
|
||||
});
|
||||
for (const auto& img : this->storageImagesSh)
|
||||
barriers.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = img.get().handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
});
|
||||
for (const auto& img : this->storageImages)
|
||||
barriers.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
|
|
@ -112,7 +179,9 @@ ManagedShader ManagedShaderBuilder::build(const vk::Vulkan& vk,
|
|||
std::move(barriers),
|
||||
vk::DescriptorSet(vk, pool, shader,
|
||||
this->sampledImages,
|
||||
this->sampledImagesSh,
|
||||
this->storageImages,
|
||||
this->storageImagesSh,
|
||||
this->imageSamplers,
|
||||
this->constantBuffers)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "lsfg-vk-common/vulkan/descriptor_pool.hpp"
|
||||
#include "lsfg-vk-common/vulkan/descriptor_set.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shader.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shared_image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
|
@ -60,6 +61,16 @@ namespace lsfgvk::backend {
|
|||
[[nodiscard]] ManagedShaderBuilder& sampleds(const std::vector<vk::Image>& images,
|
||||
size_t offset = 0, size_t count = 0);
|
||||
|
||||
// add a sampled shared image
|
||||
/// @param image image to add
|
||||
[[nodiscard]] ManagedShaderBuilder& sampled(const vk::SharedImage& image);
|
||||
/// add multiple sampled shared images
|
||||
/// @param images images to add
|
||||
/// @param offset offset into images
|
||||
/// @param count number of images to add (0 = all)
|
||||
[[nodiscard]] ManagedShaderBuilder& sampleds(const std::vector<vk::SharedImage>& images,
|
||||
size_t offset = 0, size_t count = 0);
|
||||
|
||||
/// add a storage image
|
||||
/// @param image image to add
|
||||
[[nodiscard]] ManagedShaderBuilder& storage(const vk::Image& image);
|
||||
|
|
@ -70,6 +81,16 @@ namespace lsfgvk::backend {
|
|||
[[nodiscard]] ManagedShaderBuilder& storages(const std::vector<vk::Image>& images,
|
||||
size_t offset = 0, size_t count = 0);
|
||||
|
||||
/// add a storage shared image
|
||||
/// @param image image to add
|
||||
[[nodiscard]] ManagedShaderBuilder& storage(const vk::SharedImage& image);
|
||||
/// add multiple storage shared images
|
||||
/// @param images images to add
|
||||
/// @param offset offset into images
|
||||
/// @param count number of images to add (0 = all)
|
||||
[[nodiscard]] ManagedShaderBuilder& storages(const std::vector<vk::SharedImage>& images,
|
||||
size_t offset = 0, size_t count = 0);
|
||||
|
||||
/// add a sampler
|
||||
/// @param sampler sampler to add
|
||||
[[nodiscard]] ManagedShaderBuilder& sampler(const vk::Sampler& sampler);
|
||||
|
|
@ -90,7 +111,9 @@ namespace lsfgvk::backend {
|
|||
const vk::DescriptorPool& pool, const vk::Shader& shader) const;
|
||||
private:
|
||||
std::vector<ls::R<const vk::Image>> sampledImages;
|
||||
std::vector<ls::R<const vk::SharedImage>> sampledImagesSh; // always goes first
|
||||
std::vector<ls::R<const vk::Image>> storageImages;
|
||||
std::vector<ls::R<const vk::SharedImage>> storageImagesSh;
|
||||
std::vector<ls::R<const vk::Sampler>> imageSamplers;
|
||||
std::vector<ls::R<const vk::Buffer>> constantBuffers;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "lsfg-vk-common/vulkan/fence.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/semaphore.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/timeline_semaphore.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
#include "shaderchains/alpha0.hpp"
|
||||
|
|
@ -100,15 +101,16 @@ namespace lsfgvk::backend {
|
|||
/// create a context
|
||||
/// (see lsfg-vk documentation)
|
||||
ContextImpl(const InstanceImpl& instance,
|
||||
std::pair<int, int> sourceFds, const std::vector<int>& destFds,
|
||||
const std::pair<DmaBufFD, DmaBufFD>& sourceFds,
|
||||
const std::vector<DmaBufFD>& destFds,
|
||||
VkExtent2D extent, bool hdr, float flow, bool perf);
|
||||
|
||||
/// schedule frames
|
||||
/// (see lsfg-vk documentation)
|
||||
void scheduleFrames(int waitFd, std::vector<int>& syncFds);
|
||||
private:
|
||||
std::pair<vk::Image, vk::Image> sourceImages;
|
||||
std::vector<vk::Image> destImages;
|
||||
std::pair<vk::SharedImage, vk::SharedImage> sourceImages;
|
||||
std::vector<vk::SharedImage> destImages;
|
||||
vk::Image blackImage;
|
||||
|
||||
ls::lazy<vk::Semaphore> syncSemaphore; // imported
|
||||
|
|
@ -276,7 +278,9 @@ InstanceImpl::InstanceImpl(vk::PhysicalDeviceSelector selectPhysicalDevice,
|
|||
vk.persistPipelineCache(); // will silently fail
|
||||
}
|
||||
|
||||
Context& Instance::openContext(std::pair<int, int> sourceFds, const std::vector<int>& destFds,
|
||||
Context& Instance::openContext(
|
||||
const std::pair<DmaBufFD, DmaBufFD>& sourceFds,
|
||||
const std::vector<DmaBufFD>& destFds,
|
||||
uint32_t width, uint32_t height,
|
||||
bool hdr, float flow, bool perf) {
|
||||
const VkExtent2D extent{ width, height };
|
||||
|
|
@ -288,31 +292,41 @@ Context& Instance::openContext(std::pair<int, int> sourceFds, const std::vector<
|
|||
|
||||
namespace {
|
||||
/// import source images
|
||||
std::pair<vk::Image, vk::Image> importImages(const vk::Vulkan& vk,
|
||||
const std::pair<int, int>& sourceFds,
|
||||
std::pair<vk::SharedImage, vk::SharedImage> importImages(
|
||||
const vk::Vulkan& vk,
|
||||
const std::pair<DmaBufFD, DmaBufFD>& sourceFds,
|
||||
VkExtent2D extent, VkFormat format) {
|
||||
try {
|
||||
return {
|
||||
vk::Image(vk, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, sourceFds.first),
|
||||
vk::Image(vk, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, sourceFds.second)
|
||||
vk::SharedImage(vk, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
sourceFds.first.modifier,
|
||||
sourceFds.first.layouts,
|
||||
sourceFds.first.fd),
|
||||
vk::SharedImage(vk, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
sourceFds.second.modifier,
|
||||
sourceFds.second.layouts,
|
||||
sourceFds.second.fd)
|
||||
};
|
||||
} catch (const std::exception& e) {
|
||||
throw backend::error("Unable to import destination images", e);
|
||||
}
|
||||
}
|
||||
/// import destination images
|
||||
std::vector<vk::Image> importImages(const vk::Vulkan& vk,
|
||||
const std::vector<int>& destFds,
|
||||
std::vector<vk::SharedImage> importImages(const vk::Vulkan& vk,
|
||||
const std::vector<DmaBufFD>& destFds,
|
||||
VkExtent2D extent, VkFormat format) {
|
||||
try {
|
||||
std::vector<vk::Image> destImages;
|
||||
std::vector<vk::SharedImage> destImages;
|
||||
destImages.reserve(destFds.size());
|
||||
|
||||
for (const auto& fd : destFds)
|
||||
destImages.emplace_back(vk, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, fd);
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
fd.modifier,
|
||||
fd.layouts,
|
||||
fd.fd);
|
||||
|
||||
return destImages;
|
||||
} catch (const std::exception& e) {
|
||||
|
|
@ -395,7 +409,8 @@ namespace {
|
|||
}
|
||||
|
||||
ContextImpl::ContextImpl(const InstanceImpl& instance,
|
||||
std::pair<int, int> sourceFds, const std::vector<int>& destFds,
|
||||
const std::pair<DmaBufFD, DmaBufFD>& sourceFds,
|
||||
const std::vector<DmaBufFD>& destFds,
|
||||
VkExtent2D extent, bool hdr, float flow, bool perf) :
|
||||
sourceImages(importImages(instance.getVulkan(), sourceFds,
|
||||
extent, hdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM)),
|
||||
|
|
|
|||
|
|
@ -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/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -16,11 +17,11 @@
|
|||
using namespace lsfgvk::backend;
|
||||
|
||||
Generate::Generate(const Ctx& ctx, size_t idx,
|
||||
const std::pair<vk::Image, vk::Image>& sourceImages,
|
||||
const std::pair<vk::SharedImage, vk::SharedImage>& sourceImages,
|
||||
const vk::Image& inputImage1,
|
||||
const vk::Image& inputImage2,
|
||||
const vk::Image& inputImage3,
|
||||
const vk::Image& outputImage) {
|
||||
const vk::SharedImage& outputImage) {
|
||||
// create descriptor sets
|
||||
const auto& shader = ctx.hdr ?
|
||||
ctx.shaders.get().generate_hdr : ctx.shaders.get().generate;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,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/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -27,11 +28,11 @@ namespace lsfgvk::backend {
|
|||
/// @param inputImage2 input image 2
|
||||
/// @param inputImage3 input image 3
|
||||
Generate(const Ctx& ctx, size_t idx,
|
||||
const std::pair<vk::Image, vk::Image>& sourceImages,
|
||||
const std::pair<vk::SharedImage, vk::SharedImage>& sourceImages,
|
||||
const vk::Image& inputImage1,
|
||||
const vk::Image& inputImage2,
|
||||
const vk::Image& inputImage3,
|
||||
const vk::Image& outputImage);
|
||||
const vk::SharedImage& outputImage);
|
||||
|
||||
/// render the generate shaderchain
|
||||
/// @param vk the vulkan instance
|
||||
|
|
|
|||
|
|
@ -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/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -17,7 +18,7 @@
|
|||
using namespace lsfgvk::backend;
|
||||
|
||||
Mipmaps::Mipmaps(const Ctx& ctx,
|
||||
const std::pair<vk::Image, vk::Image>& sourceImages) {
|
||||
const std::pair<vk::SharedImage, vk::SharedImage>& sourceImages) {
|
||||
// create output images for base and 6 mips
|
||||
this->images.reserve(7);
|
||||
for (uint32_t i = 0; i < 7; i++)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,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/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -23,7 +24,7 @@ namespace lsfgvk::backend {
|
|||
/// @param ctx context
|
||||
/// @param sourceImages pair of source images
|
||||
Mipmaps(const Ctx& ctx,
|
||||
const std::pair<vk::Image, vk::Image>& sourceImages);
|
||||
const std::pair<vk::SharedImage, vk::SharedImage>& sourceImages);
|
||||
|
||||
/// prepare the shaderchain initially
|
||||
/// @param images vector to fill with image handles
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ set(COMMON_SOURCES
|
|||
"src/vulkan/sampler.cpp"
|
||||
"src/vulkan/semaphore.cpp"
|
||||
"src/vulkan/shader.cpp"
|
||||
"src/vulkan/shared_image.cpp"
|
||||
"src/vulkan/timeline_semaphore.cpp"
|
||||
"src/vulkan/vulkan.cpp")
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "buffer.hpp"
|
||||
#include "image.hpp"
|
||||
#include "descriptor_pool.hpp"
|
||||
#include "shared_image.hpp"
|
||||
#include "sampler.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "vulkan.hpp"
|
||||
|
|
@ -23,14 +24,18 @@ namespace vk {
|
|||
/// @param pool the descriptor pool to allocate from
|
||||
/// @param shader the shader module this descriptor set is for
|
||||
/// @param sampledImages the sampled images to bind
|
||||
/// @param sampledImagesSh the sampled shared images to bind
|
||||
/// @param storageImages the storage images to bind
|
||||
/// @param storageImagesSh the storage shared images to bind
|
||||
/// @param samplers the samplers to bind
|
||||
/// @param buffers the buffers to bind
|
||||
/// @throws ls::vulkan_error on failure
|
||||
DescriptorSet(const vk::Vulkan& vk,
|
||||
const vk::DescriptorPool& pool, const vk::Shader& shader,
|
||||
const std::vector<ls::R<const vk::Image>>& sampledImages,
|
||||
const std::vector<ls::R<const vk::SharedImage>>& sampledImagesSh,
|
||||
const std::vector<ls::R<const vk::Image>>& storageImages,
|
||||
const std::vector<ls::R<const vk::SharedImage>>& storageImagesSh,
|
||||
const std::vector<ls::R<const vk::Sampler>>& samplers,
|
||||
const std::vector<ls::R<const vk::Buffer>>& buffers);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../helpers/pointers.hpp"
|
||||
#include "vulkan.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace vk {
|
||||
/// vulkan image
|
||||
class SharedImage {
|
||||
public:
|
||||
/// create an exported image
|
||||
/// @param vk the vulkan instance
|
||||
/// @param extent extent of the image in pixels
|
||||
/// @param format vulkan format of the image
|
||||
/// @param usage usage flags
|
||||
/// @param drmModifiers list of supported drm format modifiers
|
||||
/// @param fd output parameter for the dma-buf fd of the image memory
|
||||
/// @throws ls::vulkan_error on failure
|
||||
SharedImage(const vk::Vulkan& vk,
|
||||
VkExtent2D extent,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usage,
|
||||
const std::vector<uint64_t>& drmModifiers,
|
||||
int& fd);
|
||||
|
||||
/// create an imported image
|
||||
/// @param vk the vulkan instance
|
||||
/// @param extent extent of the image in pixels
|
||||
/// @param format vulkan format of the image
|
||||
/// @param usage usage flags
|
||||
/// @param drmModifier the drm format modifier of the image
|
||||
/// @param drmLayouts the drm offsets and row pitches of the image
|
||||
/// @param fd the dma-buf fd to import the image memory from
|
||||
/// @throws ls::vulkan_error on failure
|
||||
SharedImage(const vk::Vulkan& vk,
|
||||
VkExtent2D extent,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usage,
|
||||
uint64_t drmModifier,
|
||||
const std::vector<std::pair<uint64_t, uint64_t>>& drmLayouts,
|
||||
int fd);
|
||||
|
||||
/// get the image handle
|
||||
/// @return the image handle
|
||||
[[nodiscard]] const auto& handle() const { return this->image.get(); }
|
||||
/// get the image view handle
|
||||
/// @return the image view handle
|
||||
[[nodiscard]] const auto& imageview() const { return this->view.get(); }
|
||||
|
||||
/// get the extent of the image
|
||||
/// @return the extent of the image
|
||||
[[nodiscard]] VkExtent2D getExtent() const { return this->extent; }
|
||||
|
||||
/// get the underlying drm format modifier of the image
|
||||
/// @return the drm format modifier of the image
|
||||
[[nodiscard]] auto drmModifier() const { return this->modifier; }
|
||||
/// get the underlying drm offsets and row pitches of the image
|
||||
/// @return the drm offsets and row pitches of the image
|
||||
[[nodiscard]] const auto& drmLayouts() const { return this->layouts; }
|
||||
private:
|
||||
ls::owned_ptr<VkImage> image;
|
||||
ls::owned_ptr<VkDeviceMemory> memory;
|
||||
ls::owned_ptr<VkImageView> view;
|
||||
|
||||
VkExtent2D extent{};
|
||||
|
||||
uint64_t modifier{};
|
||||
std::vector<std::pair<uint64_t, uint64_t>> layouts;
|
||||
};
|
||||
}
|
||||
|
|
@ -109,6 +109,7 @@ namespace vk {
|
|||
PFN_vkSignalSemaphoreKHR SignalSemaphoreKHR;
|
||||
PFN_vkWaitSemaphoresKHR WaitSemaphoresKHR;
|
||||
PFN_vkGetMemoryFdKHR GetMemoryFdKHR;
|
||||
PFN_vkGetMemoryFdPropertiesKHR GetMemoryFdPropertiesKHR;
|
||||
PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR;
|
||||
PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR;
|
||||
PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
|
||||
|
|
@ -116,6 +117,9 @@ namespace vk {
|
|||
PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
|
||||
PFN_vkQueuePresentKHR QueuePresentKHR;
|
||||
PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
|
||||
|
||||
PFN_vkGetImageDrmFormatModifierPropertiesEXT GetImageDrmFormatModifierPropertiesEXT;
|
||||
PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
|
||||
};
|
||||
|
||||
/// initialize vulkan device function pointers
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/sampler.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shader.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -48,7 +49,9 @@ namespace {
|
|||
DescriptorSet::DescriptorSet(const vk::Vulkan& vk,
|
||||
const vk::DescriptorPool& pool, const vk::Shader& shader,
|
||||
const std::vector<ls::R<const vk::Image>>& sampledImages,
|
||||
const std::vector<ls::R<const vk::SharedImage>>& sampledImagesSh,
|
||||
const std::vector<ls::R<const vk::Image>>& storageImages,
|
||||
const std::vector<ls::R<const vk::SharedImage>>& storageImagesSh,
|
||||
const std::vector<ls::R<const vk::Sampler>>& samplers,
|
||||
const std::vector<ls::R<const vk::Buffer>>& buffers)
|
||||
: descriptorSet(createDescriptorSet(vk, pool, shader)) {
|
||||
|
|
@ -56,7 +59,9 @@ DescriptorSet::DescriptorSet(const vk::Vulkan& vk,
|
|||
const size_t bindingCount =
|
||||
samplers.size()
|
||||
+ sampledImages.size()
|
||||
+ sampledImagesSh.size()
|
||||
+ storageImages.size()
|
||||
+ storageImagesSh.size()
|
||||
+ buffers.size();
|
||||
|
||||
std::vector<VkWriteDescriptorSet> entries;
|
||||
|
|
@ -96,7 +101,20 @@ DescriptorSet::DescriptorSet(const vk::Vulkan& vk,
|
|||
});
|
||||
|
||||
size_t sampledIdx{32};
|
||||
for (const auto& img : sampledImages) {
|
||||
for (const auto& img : sampledImages)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = *this->descriptorSet,
|
||||
.dstBinding = static_cast<uint32_t>(sampledIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.pImageInfo = &(imageInfos.emplace_back(VkDescriptorImageInfo{
|
||||
.imageView = img.get().imageview(),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
}))
|
||||
});
|
||||
|
||||
for (const auto& img : sampledImagesSh)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = *this->descriptorSet,
|
||||
|
|
@ -108,7 +126,6 @@ DescriptorSet::DescriptorSet(const vk::Vulkan& vk,
|
|||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
size_t storageIdx{48};
|
||||
for (const auto& img : storageImages)
|
||||
|
|
@ -124,6 +141,19 @@ DescriptorSet::DescriptorSet(const vk::Vulkan& vk,
|
|||
}))
|
||||
});
|
||||
|
||||
for (const auto& img : storageImagesSh)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = *this->descriptorSet,
|
||||
.dstBinding = static_cast<uint32_t>(storageIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.pImageInfo = &(imageInfos.emplace_back(VkDescriptorImageInfo{
|
||||
.imageView = img.get().imageview(),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
}))
|
||||
});
|
||||
|
||||
vk.df().UpdateDescriptorSets(vk.dev(),
|
||||
static_cast<uint32_t>(entries.size()), entries.data(), 0, VK_NULL_HANDLE);
|
||||
}
|
||||
|
|
|
|||
374
lsfg-vk-common/src/vulkan/shared_image.cpp
Normal file
374
lsfg-vk-common/src/vulkan/shared_image.cpp
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "lsfg-vk-common/vulkan/shared_image.hpp"
|
||||
#include "lsfg-vk-common/helpers/errors.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace vk;
|
||||
|
||||
namespace {
|
||||
/* EXPORTABLE - DMA-BUF */
|
||||
|
||||
/// create an image that can be imported from a dma-buf fd
|
||||
ls::owned_ptr<VkImage> createDMAImportableImage(const vk::Vulkan& vk,
|
||||
VkExtent2D extent, VkFormat format, VkImageUsageFlags usage,
|
||||
uint64_t drmModifier,
|
||||
const std::vector<std::pair<uint64_t, uint64_t>>& drmLayouts) {
|
||||
VkImage handle{};
|
||||
|
||||
// create VkImage
|
||||
std::vector<VkSubresourceLayout> layouts(drmLayouts.size());
|
||||
for (size_t i = 0; i < layouts.size(); i++)
|
||||
layouts[i] = VkSubresourceLayout {
|
||||
.offset = drmLayouts.at(i).first,
|
||||
.rowPitch = drmLayouts.at(i).second
|
||||
};
|
||||
const VkImageDrmFormatModifierExplicitCreateInfoEXT explicitModifierInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
|
||||
.drmFormatModifier = drmModifier,
|
||||
.drmFormatModifierPlaneCount = 1,
|
||||
.pPlaneLayouts = layouts.data()
|
||||
};
|
||||
const VkExternalMemoryImageCreateInfo externalInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
.pNext = &explicitModifierInfo,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
|
||||
};
|
||||
const VkImageCreateInfo imageInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = &externalInfo,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = format,
|
||||
.extent = {
|
||||
.width = extent.width,
|
||||
.height = extent.height,
|
||||
.depth = 1
|
||||
},
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
|
||||
.usage = usage,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||
};
|
||||
auto res = vk.df().CreateImage(vk.dev(), &imageInfo, VK_NULL_HANDLE, &handle);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkCreateImage() failed");
|
||||
|
||||
return ls::owned_ptr<VkImage>(
|
||||
new VkImage(handle),
|
||||
[dev = vk.dev(), defunc = vk.df().DestroyImage](VkImage& image) {
|
||||
defunc(dev, image, VK_NULL_HANDLE);
|
||||
}
|
||||
);
|
||||
}
|
||||
/// import image memory from a dma-buf fd
|
||||
ls::owned_ptr<VkDeviceMemory> importDMADeviceMemory(const vk::Vulkan& vk, VkImage image, int fd) {
|
||||
VkDeviceMemory handle{};
|
||||
|
||||
// find suitable memory type
|
||||
VkMemoryFdPropertiesKHR propsFd{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR
|
||||
};
|
||||
auto res = vk.df().GetMemoryFdPropertiesKHR(vk.dev(),
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, fd, &propsFd);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkGetMemoryFdPropertiesKHR() failed");
|
||||
|
||||
VkMemoryRequirements reqs{};
|
||||
vk.df().GetImageMemoryRequirements(vk.dev(), image, &reqs);
|
||||
|
||||
reqs.memoryTypeBits &= propsFd.memoryTypeBits;
|
||||
|
||||
auto mti = vk.findMemoryTypeIndex(
|
||||
reqs.memoryTypeBits,
|
||||
false
|
||||
);
|
||||
if (!mti.has_value())
|
||||
throw ls::vulkan_error(VK_ERROR_UNKNOWN, "no suitable memory type found");
|
||||
|
||||
// create VkDeviceMemory
|
||||
const VkImportMemoryFdInfoKHR importInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
||||
.fd = fd
|
||||
};
|
||||
const VkMemoryAllocateInfo memoryInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &importInfo,
|
||||
.allocationSize = reqs.size,
|
||||
.memoryTypeIndex = *mti
|
||||
};
|
||||
res = vk.df().AllocateMemory(vk.dev(), &memoryInfo, VK_NULL_HANDLE, &handle);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkAllocateMemory() failed");
|
||||
|
||||
// bind memory to image
|
||||
res = vk.df().BindImageMemory(vk.dev(), image, handle, 0);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkBindImageMemory() failed");
|
||||
|
||||
return ls::owned_ptr<VkDeviceMemory>(
|
||||
new VkDeviceMemory(handle),
|
||||
[dev = vk.dev(), defunc = vk.df().FreeMemory](VkDeviceMemory& memory) {
|
||||
defunc(dev, memory, VK_NULL_HANDLE);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* IMPORTABLE - DMA-BUF */
|
||||
|
||||
/// create an image that can be exported to a dma-buf fd
|
||||
ls::owned_ptr<VkImage> createDMAExportableImage(const vk::Vulkan& vk,
|
||||
VkExtent2D extent, VkFormat format, VkImageUsageFlags usage,
|
||||
const std::vector<uint64_t>& drmModifiers) {
|
||||
VkImage handle{};
|
||||
|
||||
// create VkImage
|
||||
const VkImageDrmFormatModifierListCreateInfoEXT explicitModifierInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
|
||||
.drmFormatModifierCount = static_cast<uint32_t>(drmModifiers.size()),
|
||||
.pDrmFormatModifiers = drmModifiers.data()
|
||||
};
|
||||
const VkExternalMemoryImageCreateInfo externalInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
.pNext = &explicitModifierInfo,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
|
||||
};
|
||||
const VkImageCreateInfo imageInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = &externalInfo,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = format,
|
||||
.extent = {
|
||||
.width = extent.width,
|
||||
.height = extent.height,
|
||||
.depth = 1
|
||||
},
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
|
||||
.usage = usage,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||
};
|
||||
auto res = vk.df().CreateImage(vk.dev(), &imageInfo, VK_NULL_HANDLE, &handle);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkCreateImage() failed");
|
||||
|
||||
return ls::owned_ptr<VkImage>(
|
||||
new VkImage(handle),
|
||||
[dev = vk.dev(), defunc = vk.df().DestroyImage](VkImage& image) {
|
||||
defunc(dev, image, VK_NULL_HANDLE);
|
||||
}
|
||||
);
|
||||
}
|
||||
/// export image memory to a dma-buf fd
|
||||
ls::owned_ptr<VkDeviceMemory> exportDMADeviceMemory(const vk::Vulkan& vk, VkImage image, int& fd) {
|
||||
VkDeviceMemory handle{};
|
||||
|
||||
// find suitable memory type
|
||||
VkMemoryRequirements reqs{};
|
||||
vk.df().GetImageMemoryRequirements(vk.dev(), image, &reqs);
|
||||
|
||||
auto mti = vk.findMemoryTypeIndex(
|
||||
reqs.memoryTypeBits,
|
||||
false
|
||||
);
|
||||
if (!mti.has_value())
|
||||
throw ls::vulkan_error(VK_ERROR_UNKNOWN, "no suitable memory type found");
|
||||
|
||||
// create VkDeviceMemory
|
||||
const VkExportMemoryAllocateInfoKHR importInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
|
||||
};
|
||||
const VkMemoryAllocateInfo memoryInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &importInfo,
|
||||
.allocationSize = reqs.size,
|
||||
.memoryTypeIndex = *mti
|
||||
};
|
||||
auto res = vk.df().AllocateMemory(vk.dev(), &memoryInfo, VK_NULL_HANDLE, &handle);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkAllocateMemory() failed");
|
||||
|
||||
// bind memory to image
|
||||
res = vk.df().BindImageMemory(vk.dev(), image, handle, 0);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkBindImageMemory() failed");
|
||||
|
||||
// export dma-buf fd
|
||||
const VkMemoryGetFdInfoKHR exportInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
|
||||
.memory = handle,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
|
||||
};
|
||||
res = vk.df().GetMemoryFdKHR(vk.dev(), &exportInfo, &fd);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkGetMemoryFdKHR() failed");
|
||||
|
||||
return ls::owned_ptr<VkDeviceMemory>(
|
||||
new VkDeviceMemory(handle),
|
||||
[dev = vk.dev(), defunc = vk.df().FreeMemory](VkDeviceMemory& memory) {
|
||||
defunc(dev, memory, VK_NULL_HANDLE);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* GENERAL */
|
||||
|
||||
/// create an image view
|
||||
ls::owned_ptr<VkImageView> createImageView(const vk::Vulkan& vk,
|
||||
VkImage image, VkFormat format) {
|
||||
VkImageView handle{};
|
||||
|
||||
const VkImageViewCreateInfo viewInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = format,
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
auto res = vk.df().CreateImageView(vk.dev(), &viewInfo, VK_NULL_HANDLE, &handle);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkCreateImageView() failed");
|
||||
|
||||
return ls::owned_ptr<VkImageView>(
|
||||
new VkImageView(handle),
|
||||
[dev = vk.dev(), defunc = vk.df().DestroyImageView](VkImageView& view) {
|
||||
defunc(dev, view, VK_NULL_HANDLE);
|
||||
}
|
||||
);
|
||||
}
|
||||
/// get the drm format modifier of an image
|
||||
uint64_t getImageDrmModifier(const vk::Vulkan& vk, VkImage image) {
|
||||
VkImageDrmFormatModifierPropertiesEXT props{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT
|
||||
};
|
||||
auto res = vk.df().GetImageDrmFormatModifierPropertiesEXT(vk.dev(), image, &props);
|
||||
if (res != VK_SUCCESS)
|
||||
throw ls::vulkan_error(res, "vkGetImageDrmFormatModifierPropertiesEXT() failed");
|
||||
|
||||
return props.drmFormatModifier;
|
||||
}
|
||||
/// get the drm offsets and row pitches of an image
|
||||
std::vector<std::pair<uint64_t, uint64_t>> getImageLayouts(const vk::Vulkan& vk,
|
||||
VkImage image, uint64_t drmModifier) {
|
||||
std::vector<std::pair<uint64_t, uint64_t>> result;
|
||||
|
||||
// fetch drm modifier information
|
||||
VkDrmFormatModifierPropertiesList2EXT formats{
|
||||
.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT,
|
||||
};
|
||||
VkPhysicalDeviceProperties2 props{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||
.pNext = &formats
|
||||
};
|
||||
vk.fi().GetPhysicalDeviceProperties2(vk.physdev(), &props);
|
||||
|
||||
std::vector<VkDrmFormatModifierProperties2EXT> formatProps(formats.drmFormatModifierCount);
|
||||
formats.pDrmFormatModifierProperties = formatProps.data();
|
||||
|
||||
vk.fi().GetPhysicalDeviceProperties2(vk.physdev(), &props);
|
||||
|
||||
// find plane count for the modifier
|
||||
std::optional<size_t> planeCount;
|
||||
for (const auto& fp : formatProps) {
|
||||
if (fp.drmFormatModifier != drmModifier)
|
||||
continue;
|
||||
|
||||
planeCount.emplace(fp.drmFormatModifierPlaneCount);
|
||||
}
|
||||
|
||||
if (!planeCount.has_value())
|
||||
throw ls::vulkan_error(VK_ERROR_UNKNOWN, "invalid drm modifier");
|
||||
|
||||
// get offsets and row pitches
|
||||
const std::vector<VkImageAspectFlagBits> bits{
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT,
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT,
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT,
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT,
|
||||
};
|
||||
|
||||
result.reserve(*planeCount);
|
||||
for (size_t i = 0; i < *planeCount; i++) {
|
||||
VkSubresourceLayout layout{};
|
||||
|
||||
const VkImageSubresource subresource{
|
||||
.aspectMask = bits.at(i),
|
||||
};
|
||||
vk.df().GetImageSubresourceLayout(vk.dev(), image, &subresource, &layout);
|
||||
|
||||
result.emplace_back(
|
||||
layout.offset,
|
||||
layout.rowPitch
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
SharedImage::SharedImage(const vk::Vulkan& vk,
|
||||
VkExtent2D extent,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usage,
|
||||
const std::vector<uint64_t>& drmModifiers,
|
||||
int& fd) :
|
||||
image(createDMAExportableImage(vk,
|
||||
extent, format, usage,
|
||||
drmModifiers
|
||||
)),
|
||||
memory(exportDMADeviceMemory(vk,
|
||||
*this->image,
|
||||
fd
|
||||
)),
|
||||
view(createImageView(vk,
|
||||
*this->image,
|
||||
format
|
||||
)),
|
||||
extent(extent),
|
||||
modifier(getImageDrmModifier(vk, *this->image)),
|
||||
layouts(getImageLayouts(vk, *this->image, this->modifier)) {
|
||||
}
|
||||
|
||||
|
||||
SharedImage::SharedImage(const vk::Vulkan& vk,
|
||||
VkExtent2D extent,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usage,
|
||||
uint64_t drmModifier,
|
||||
const std::vector<std::pair<uint64_t, uint64_t>>& drmLayouts,
|
||||
int fd) :
|
||||
image(createDMAImportableImage(vk,
|
||||
extent, format, usage,
|
||||
drmModifier, drmLayouts
|
||||
)),
|
||||
memory(importDMADeviceMemory(vk,
|
||||
*this->image,
|
||||
fd
|
||||
)),
|
||||
view(createImageView(vk,
|
||||
*this->image,
|
||||
format
|
||||
)),
|
||||
extent(extent),
|
||||
modifier(getImageDrmModifier(vk, *this->image)),
|
||||
layouts(getImageLayouts(vk, *this->image, this->modifier)) {
|
||||
}
|
||||
|
|
@ -177,6 +177,8 @@ namespace {
|
|||
};
|
||||
const std::vector<const char*> requestedExtensions{
|
||||
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
|
||||
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
|
||||
VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME
|
||||
};
|
||||
|
|
@ -379,6 +381,7 @@ VulkanDeviceFuncs vk::initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevi
|
|||
.SignalSemaphoreKHR = dpa<PFN_vkSignalSemaphoreKHR>(f, d, "vkSignalSemaphoreKHR"),
|
||||
.WaitSemaphoresKHR = dpa<PFN_vkWaitSemaphoresKHR>(f, d, "vkWaitSemaphoresKHR"),
|
||||
.GetMemoryFdKHR = dpa<PFN_vkGetMemoryFdKHR>(f, d, "vkGetMemoryFdKHR"),
|
||||
.GetMemoryFdPropertiesKHR = dpa<PFN_vkGetMemoryFdPropertiesKHR>(f, d, "vkGetMemoryFdPropertiesKHR"),
|
||||
.ImportSemaphoreFdKHR = dpa<PFN_vkImportSemaphoreFdKHR>(f, d, "vkImportSemaphoreFdKHR"),
|
||||
.GetSemaphoreFdKHR = dpa<PFN_vkGetSemaphoreFdKHR>(f, d, "vkGetSemaphoreFdKHR"),
|
||||
|
||||
|
|
@ -391,7 +394,11 @@ VulkanDeviceFuncs vk::initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevi
|
|||
.QueuePresentKHR = graphical ?
|
||||
dpa<PFN_vkQueuePresentKHR>(f, d, "vkQueuePresentKHR") : nullptr,
|
||||
.DestroySwapchainKHR = graphical ?
|
||||
dpa<PFN_vkDestroySwapchainKHR>(f, d, "vkDestroySwapchainKHR") : nullptr
|
||||
dpa<PFN_vkDestroySwapchainKHR>(f, d, "vkDestroySwapchainKHR") : nullptr,
|
||||
|
||||
.GetImageDrmFormatModifierPropertiesEXT = dpa<PFN_vkGetImageDrmFormatModifierPropertiesEXT>(f, d,
|
||||
"vkGetImageDrmFormatModifierPropertiesEXT"),
|
||||
.GetImageSubresourceLayout = dpa<PFN_vkGetImageSubresourceLayout>(f, d, "vkGetImageSubresourceLayout")
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,13 @@ void Root::modifyDeviceCreateInfo(VkDeviceCreateInfo& createInfo,
|
|||
{
|
||||
"VK_KHR_external_memory",
|
||||
"VK_KHR_external_memory_fd",
|
||||
"VK_EXT_external_memory_dma_buf",
|
||||
"VK_KHR_image_format_list",
|
||||
"VK_KHR_bind_memory2",
|
||||
"VK_KHR_maintenance1",
|
||||
"VK_KHR_get_memory_requirements2",
|
||||
"VK_KHR_sampler_ycbcr_conversion",
|
||||
"VK_EXT_image_drm_format_modifier",
|
||||
"VK_KHR_external_semaphore",
|
||||
"VK_KHR_external_semaphore_fd",
|
||||
"VK_KHR_timeline_semaphore"
|
||||
|
|
@ -120,7 +127,7 @@ void Root::modifyDeviceCreateInfo(VkDeviceCreateInfo& createInfo,
|
|||
);
|
||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||
createInfo.ppEnabledExtensionNames = extensions.data();
|
||||
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
#include "lsfg-vk-common/helpers/errors.hpp"
|
||||
#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/semaphore.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
|
@ -76,24 +76,46 @@ Swapchain::Swapchain(const vk::Vulkan& vk, backend::Instance& backend,
|
|||
std::vector<int> sourceFds(2);
|
||||
std::vector<int> destinationFds(this->profile.multiplier - 1);
|
||||
|
||||
const std::vector<uint64_t> modifiers = { DRM_FORMAT_MOD_LINEAR };
|
||||
|
||||
this->sourceImages.reserve(sourceFds.size());
|
||||
for (int& fd : sourceFds)
|
||||
this->sourceImages.emplace_back(vk,
|
||||
extent, hdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
std::nullopt, &fd);
|
||||
modifiers, fd);
|
||||
|
||||
this->destinationImages.reserve(destinationFds.size());
|
||||
for (int& fd : destinationFds)
|
||||
this->destinationImages.emplace_back(vk,
|
||||
extent, hdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
std::nullopt, &fd);
|
||||
modifiers, fd);
|
||||
|
||||
try {
|
||||
const backend::DmaBufFD fd0{
|
||||
.fd = sourceFds.at(0),
|
||||
.modifier = this->sourceImages.at(0).drmModifier(),
|
||||
.layouts = this->sourceImages.at(0).drmLayouts()
|
||||
};
|
||||
const backend::DmaBufFD fd1{
|
||||
.fd = sourceFds.at(1),
|
||||
.modifier = this->sourceImages.at(1).drmModifier(),
|
||||
.layouts = this->sourceImages.at(1).drmLayouts()
|
||||
};
|
||||
|
||||
std::vector<backend::DmaBufFD> destFdNs;
|
||||
destFdNs.reserve(this->destinationImages.size());
|
||||
for (size_t i = 0; i < this->destinationImages.size(); i++)
|
||||
destFdNs.push_back(backend::DmaBufFD{
|
||||
.fd = destinationFds.at(i),
|
||||
.modifier = this->destinationImages.at(i).drmModifier(),
|
||||
.layouts = this->destinationImages.at(i).drmLayouts()
|
||||
});
|
||||
|
||||
this->ctx = ls::owned_ptr<ls::R<backend::Context>>(
|
||||
new ls::R<backend::Context>(backend.openContext(
|
||||
{ sourceFds.at(0), sourceFds.at(1) }, destinationFds,
|
||||
{ fd0, fd1 }, destFdNs,
|
||||
extent.width, extent.height,
|
||||
hdr, 1.0F / this->profile.flow_scale, this->profile.performance_mode
|
||||
)),
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/fence.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/semaphore.hpp"
|
||||
#include "lsfg-vk-common/vulkan/timeline_semaphore.hpp"
|
||||
#include "lsfg-vk-common/vulkan/shared_image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
|
@ -59,8 +58,8 @@ namespace lsfgvk::layer {
|
|||
void* next_chain, uint32_t imageIdx,
|
||||
const std::vector<VkSemaphore>& semaphores);
|
||||
private:
|
||||
std::vector<vk::Image> sourceImages;
|
||||
std::vector<vk::Image> destinationImages;
|
||||
std::vector<vk::SharedImage> sourceImages;
|
||||
std::vector<vk::SharedImage> destinationImages;
|
||||
ls::lazy<vk::Semaphore> syncSemaphore;
|
||||
|
||||
ls::lazy<vk::CommandBuffer> renderCommandBuffer;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue