host image copy

This commit is contained in:
PancakeTAS 2025-06-30 01:10:54 +02:00
parent 6b21e1f298
commit bdeae9b8d0
No known key found for this signature in database
4 changed files with 107 additions and 4 deletions

16
include/utils/upload.hpp Normal file
View file

@ -0,0 +1,16 @@
#ifndef UPLOAD_HPP
#define UPLOAD_HPP
#include "core/image.hpp"
#include "device.hpp"
#include <string>
namespace Upload {
void upload(const Vulkan::Device& device,
Vulkan::Core::Image& image, const std::string& path);
}
#endif // UPLOAD_HPP

View file

@ -3,10 +3,13 @@
#include <optional>
#include <vector>
#include <vulkan/vulkan_core.h>
using namespace Vulkan;
const std::vector<const char*> requiredExtensions = {
"VK_EXT_host_image_copy"
};
Device::Device(const Instance& instance) {
// get all physical devices
uint32_t deviceCount{};
@ -50,8 +53,13 @@ Device::Device(const Instance& instance) {
// create logical device
const float queuePriority{1.0F}; // highest priority
VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeatures{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT,
.hostImageCopy = VK_TRUE
};
VkPhysicalDeviceVulkan13Features features13{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
.pNext = &hostImageCopyFeatures,
.synchronization2 = VK_TRUE
};
const VkPhysicalDeviceVulkan12Features features12{
@ -70,7 +78,9 @@ Device::Device(const Instance& instance) {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &features12,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &computeQueueDesc
.pQueueCreateInfos = &computeQueueDesc,
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
.ppEnabledExtensionNames = requiredExtensions.data()
};
VkDevice deviceHandle{};
res = vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);

View file

@ -7,6 +7,7 @@
#include "instance.hpp"
#include "shaderchains/downsample.hpp"
#include "utils/global.hpp"
#include "utils/upload.hpp"
#include <iostream>
@ -23,11 +24,13 @@ int main() {
Globals::initializeGlobals(device);
// create initialization resources
const Core::Image inputImage(
Core::Image inputImage(
device, { 2560, 1411 }, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT
| VK_IMAGE_USAGE_HOST_TRANSFER_BIT, // (remove in prod)
VK_IMAGE_ASPECT_COLOR_BIT
);
Upload::upload(device, inputImage, "rsc/images/source.dds");
// create the shaderchains
Shaderchains::Downsample downsample(device, descriptorPool, inputImage);

74
src/utils/upload.cpp Normal file
View file

@ -0,0 +1,74 @@
#include "utils/upload.hpp"
#include "utils/exceptions.hpp"
#include <fstream>
#include <vector>
#include <vulkan/vulkan_core.h>
using namespace Upload;
void Upload::upload(const Vulkan::Device& device,
Vulkan::Core::Image& image, const std::string& path) {
auto vkTransitionImageLayoutEXT = reinterpret_cast<PFN_vkTransitionImageLayoutEXT>(
vkGetDeviceProcAddr(device.handle(), "vkTransitionImageLayoutEXT"));
auto vkCopyMemoryToImageEXT = reinterpret_cast<PFN_vkCopyMemoryToImageEXT>(
vkGetDeviceProcAddr(device.handle(), "vkCopyMemoryToImageEXT"));
const VkHostImageLayoutTransitionInfoEXT transitionInfo{
.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
.image = image.handle(),
.oldLayout = image.getLayout(),
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.subresourceRange = {
.aspectMask = image.getAspectFlags(),
.levelCount = 1,
.layerCount = 1
}
};
image.setLayout(VK_IMAGE_LAYOUT_GENERAL);
auto res = vkTransitionImageLayoutEXT(device.handle(), 1, &transitionInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Failed to transition image layout for upload");
// read shader bytecode
std::ifstream file(path, std::ios::ate | std::ios::binary);
if (!file)
throw std::system_error(errno, std::generic_category(), "Failed to open shader file: " + path);
std::streamsize size = file.tellg();
size -= 124 - 4;
std::vector<uint8_t> code(static_cast<size_t>(size));
file.seekg(0, std::ios::beg);
if (!file.read(reinterpret_cast<char*>(code.data()), size))
throw std::system_error(errno, std::generic_category(), "Failed to read shader file: " + path);
file.close();
// copy data to image
auto extent = image.getExtent();
const VkMemoryToImageCopyEXT copyInfo{
.sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
.pHostPointer = code.data(),
.imageSubresource = {
.aspectMask = image.getAspectFlags(),
.layerCount = 1
},
.imageExtent = {
.width = extent.width,
.height = extent.height,
.depth = 1
},
};
const VkCopyMemoryToImageInfoEXT operationInfo{
.sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
.dstImage = image.handle(),
.dstImageLayout = image.getLayout(),
.regionCount = 1,
.pRegions = &copyInfo,
};
res = vkCopyMemoryToImageEXT(device.handle(), &operationInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Failed to copy memory to image");
}