mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
feat(test): write main test
This commit is contained in:
parent
a90593fdc1
commit
405733d50e
4 changed files with 185 additions and 10 deletions
|
|
@ -48,6 +48,21 @@ namespace LSFG::Core {
|
||||||
Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
||||||
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags, int fd);
|
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags, int fd);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Create the image and export the backing fd
|
||||||
|
///
|
||||||
|
/// @param device Vulkan device
|
||||||
|
/// @param extent Extent of the image in pixels.
|
||||||
|
/// @param format Vulkan format of the image
|
||||||
|
/// @param usage Usage flags for the image
|
||||||
|
/// @param aspectFlags Aspect flags for the image view
|
||||||
|
/// @param fd Pointer to an integer where the file descriptor will be stored.
|
||||||
|
///
|
||||||
|
/// @throws LSFG::vulkan_error if object creation fails.
|
||||||
|
///
|
||||||
|
Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
||||||
|
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags, int* fd);
|
||||||
|
|
||||||
/// Get the Vulkan handle.
|
/// Get the Vulkan handle.
|
||||||
[[nodiscard]] auto handle() const { return *this->image; }
|
[[nodiscard]] auto handle() const { return *this->image; }
|
||||||
/// Get the Vulkan device memory handle.
|
/// Get the Vulkan device memory handle.
|
||||||
|
|
|
||||||
|
|
@ -240,3 +240,136 @@ Image::Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// second shared memory constructors
|
||||||
|
|
||||||
|
Image::Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
||||||
|
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags, int* fd)
|
||||||
|
: extent(extent), format(format), aspectFlags(aspectFlags) {
|
||||||
|
// create image
|
||||||
|
const VkExternalMemoryImageCreateInfo externalInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||||
|
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
|
||||||
|
};
|
||||||
|
const VkImageCreateInfo desc{
|
||||||
|
.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,
|
||||||
|
.usage = usage,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
VkImage imageHandle{};
|
||||||
|
auto res = vkCreateImage(device.handle(), &desc, nullptr, &imageHandle);
|
||||||
|
if (res != VK_SUCCESS || imageHandle == VK_NULL_HANDLE)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to create Vulkan image");
|
||||||
|
|
||||||
|
// find memory type
|
||||||
|
VkPhysicalDeviceMemoryProperties memProps;
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(device.getPhysicalDevice(), &memProps);
|
||||||
|
|
||||||
|
VkMemoryRequirements memReqs;
|
||||||
|
vkGetImageMemoryRequirements(device.handle(), imageHandle, &memReqs);
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||||
|
std::optional<uint32_t> memType{};
|
||||||
|
for (uint32_t i = 0; i < memProps.memoryTypeCount; ++i) {
|
||||||
|
if ((memReqs.memoryTypeBits & (1 << i)) && // NOLINTBEGIN
|
||||||
|
(memProps.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
|
||||||
|
memType.emplace(i);
|
||||||
|
break;
|
||||||
|
} // NOLINTEND
|
||||||
|
}
|
||||||
|
if (!memType.has_value())
|
||||||
|
throw LSFG::vulkan_error(VK_ERROR_UNKNOWN, "Unable to find memory type for image");
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
// allocate and bind memory
|
||||||
|
const VkMemoryDedicatedAllocateInfoKHR dedicatedInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
|
||||||
|
.image = imageHandle,
|
||||||
|
};
|
||||||
|
const VkExportMemoryAllocateInfo exportInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = &dedicatedInfo,
|
||||||
|
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
|
||||||
|
};
|
||||||
|
const VkMemoryAllocateInfo allocInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = &exportInfo,
|
||||||
|
.allocationSize = memReqs.size,
|
||||||
|
.memoryTypeIndex = memType.value()
|
||||||
|
};
|
||||||
|
VkDeviceMemory memoryHandle{};
|
||||||
|
res = vkAllocateMemory(device.handle(), &allocInfo, nullptr, &memoryHandle);
|
||||||
|
if (res != VK_SUCCESS || memoryHandle == VK_NULL_HANDLE)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to allocate memory for Vulkan image");
|
||||||
|
|
||||||
|
res = vkBindImageMemory(device.handle(), imageHandle, memoryHandle, 0);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to bind memory to Vulkan image");
|
||||||
|
|
||||||
|
// obtain the sharing fd
|
||||||
|
const VkMemoryGetFdInfoKHR fdInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
|
||||||
|
.memory = memoryHandle,
|
||||||
|
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
|
||||||
|
};
|
||||||
|
res = vkGetMemoryFdKHR(device.handle(), &fdInfo, fd);
|
||||||
|
if (res != VK_SUCCESS || *fd < 0)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to obtain sharing fd for Vulkan image");
|
||||||
|
|
||||||
|
// create image view
|
||||||
|
const VkImageViewCreateInfo viewDesc{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
|
.image = imageHandle,
|
||||||
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||||
|
.format = format,
|
||||||
|
.components = {
|
||||||
|
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
.a = VK_COMPONENT_SWIZZLE_IDENTITY
|
||||||
|
},
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = aspectFlags,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImageView viewHandle{};
|
||||||
|
res = vkCreateImageView(device.handle(), &viewDesc, nullptr, &viewHandle);
|
||||||
|
if (res != VK_SUCCESS || viewHandle == VK_NULL_HANDLE)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to create image view");
|
||||||
|
|
||||||
|
// store objects in shared ptr
|
||||||
|
this->layout = std::make_shared<VkImageLayout>(VK_IMAGE_LAYOUT_UNDEFINED);
|
||||||
|
this->image = std::shared_ptr<VkImage>(
|
||||||
|
new VkImage(imageHandle),
|
||||||
|
[dev = device.handle()](VkImage* img) {
|
||||||
|
vkDestroyImage(dev, *img, nullptr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this->memory = std::shared_ptr<VkDeviceMemory>(
|
||||||
|
new VkDeviceMemory(memoryHandle),
|
||||||
|
[dev = device.handle()](VkDeviceMemory* mem) {
|
||||||
|
vkFreeMemory(dev, *mem, nullptr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this->view = std::shared_ptr<VkImageView>(
|
||||||
|
new VkImageView(viewHandle),
|
||||||
|
[dev = device.handle()](VkImageView* imgView) {
|
||||||
|
vkDestroyImageView(dev, *imgView, nullptr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ set_target_properties(lsfg-vk-test PROPERTIES
|
||||||
target_include_directories(lsfg-vk-test
|
target_include_directories(lsfg-vk-test
|
||||||
PRIVATE include)
|
PRIVATE include)
|
||||||
target_link_libraries(lsfg-vk-test PUBLIC
|
target_link_libraries(lsfg-vk-test PUBLIC
|
||||||
vulkan lsfg-vk)
|
lsfg-vk lsfg-vk-framegen
|
||||||
|
vulkan)
|
||||||
|
|
||||||
# diagnostics
|
# diagnostics
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
|
#include "common/utils.hpp"
|
||||||
|
#include "core/commandpool.hpp"
|
||||||
#include "core/device.hpp"
|
#include "core/device.hpp"
|
||||||
|
#include "core/image.hpp"
|
||||||
#include "core/instance.hpp"
|
#include "core/instance.hpp"
|
||||||
#include "extract/extract.hpp"
|
#include "extract/extract.hpp"
|
||||||
#include "mini/image.hpp"
|
|
||||||
#include "utils.hpp"
|
|
||||||
|
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
#include <renderdoc_app.h>
|
#include <renderdoc_app.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -20,6 +23,7 @@ using namespace LSFG;
|
||||||
|
|
||||||
const VkExtent2D SRC_EXTENT = { 2560 , 1440 };
|
const VkExtent2D SRC_EXTENT = { 2560 , 1440 };
|
||||||
const VkFormat SRC_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
|
const VkFormat SRC_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
const std::string EMPTY_FILE = "test/empty.dds";
|
||||||
const std::array<std::string, 2> SRC_FILES = {
|
const std::array<std::string, 2> SRC_FILES = {
|
||||||
"test/f0.dds",
|
"test/f0.dds",
|
||||||
"test/f1.dds"
|
"test/f1.dds"
|
||||||
|
|
@ -53,26 +57,28 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create images for frame generation
|
/// Create images for frame generation
|
||||||
void create_images(const Core::Device& device,
|
std::pair<Core::Image, Core::Image> create_images(const Core::Device& device,
|
||||||
std::array<int, 2>& fds,
|
std::array<int, 2>& fds,
|
||||||
std::vector<int>& outFds, std::vector<Mini::Image>& out_n) {
|
std::vector<int>& outFds, std::vector<Core::Image>& out_n) {
|
||||||
const Mini::Image frame_0{device.handle(), device.getPhysicalDevice(),
|
const Core::Image frame_0{device,
|
||||||
SRC_EXTENT, SRC_FORMAT,
|
SRC_EXTENT, SRC_FORMAT,
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
&fds.at(0)
|
&fds.at(0)
|
||||||
};
|
};
|
||||||
const Mini::Image frame_1{device.handle(), device.getPhysicalDevice(),
|
const Core::Image frame_1{device,
|
||||||
SRC_EXTENT, SRC_FORMAT,
|
SRC_EXTENT, SRC_FORMAT,
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
&fds.at(1)
|
&fds.at(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < (MULTIPLIER - 1); i++)
|
for (size_t i = 0; i < (MULTIPLIER - 1); i++)
|
||||||
out_n.at(i) = Mini::Image{device.handle(), device.getPhysicalDevice(),
|
out_n.at(i) = Core::Image{device,
|
||||||
SRC_EXTENT, SRC_FORMAT,
|
SRC_EXTENT, SRC_FORMAT,
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
&outFds.at(i)
|
&outFds.at(i)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return { frame_0, frame_1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the LSFG context.
|
/// Create the LSFG context.
|
||||||
|
|
@ -99,7 +105,8 @@ namespace {
|
||||||
namespace {
|
namespace {
|
||||||
std::array<int, 2> fds{};
|
std::array<int, 2> fds{};
|
||||||
std::vector<int> outFds(MULTIPLIER - 1);
|
std::vector<int> outFds(MULTIPLIER - 1);
|
||||||
std::vector<Mini::Image> out_n(MULTIPLIER - 1);
|
std::pair<Core::Image, Core::Image> frames{};
|
||||||
|
std::vector<Core::Image> out_n(MULTIPLIER - 1);
|
||||||
int32_t lsfg_id{};
|
int32_t lsfg_id{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,14 +114,33 @@ int main() {
|
||||||
// initialize host Vulkan
|
// initialize host Vulkan
|
||||||
const Core::Instance instance{};
|
const Core::Instance instance{};
|
||||||
const Core::Device device{instance, 0x1463ABAC};
|
const Core::Device device{instance, 0x1463ABAC};
|
||||||
|
const Core::CommandPool commandPool{device};
|
||||||
|
|
||||||
// setup test
|
// setup test
|
||||||
setup_renderdoc();
|
setup_renderdoc();
|
||||||
create_images(device, fds, outFds, out_n);
|
frames = create_images(device, fds, outFds, out_n);
|
||||||
lsfg_id = create_lsfg(fds, outFds);
|
lsfg_id = create_lsfg(fds, outFds);
|
||||||
|
|
||||||
|
Utils::clearImage(device, frames.first);
|
||||||
|
Utils::clearImage(device, frames.second);
|
||||||
|
|
||||||
// run
|
// run
|
||||||
for (size_t fc = 0; fc < SRC_FILES.size(); fc++) {
|
for (size_t fc = 0; fc < SRC_FILES.size(); fc++) {
|
||||||
|
if (fc % 2 == 0)
|
||||||
|
Utils::uploadImage(device, commandPool, frames.first, SRC_FILES.at(fc));
|
||||||
|
else
|
||||||
|
Utils::uploadImage(device, commandPool, frames.second, SRC_FILES.at(fc));
|
||||||
|
|
||||||
|
if (rdoc) rdoc->StartFrameCapture(nullptr, nullptr);
|
||||||
|
|
||||||
|
// run the present
|
||||||
|
const std::vector<int> null_sems(MULTIPLIER - 1, -1);
|
||||||
|
presentContext(lsfg_id, -1, null_sems);
|
||||||
|
|
||||||
|
// wait until the present is done
|
||||||
|
usleep(1000 * 100);
|
||||||
|
|
||||||
|
if (rdoc) rdoc->EndFrameCapture(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy test
|
// destroy test
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue