#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_TRANSFER_H_ #define EMULATOR_SRC_GRAPHICS_HOST_GPU_TRANSFER_H_ #include "common/abi.h" #include "common/common.h" #include "graphics/host_gpu/gpuTiler.h" #include "graphics/host_gpu/vulkanCommon.h" #include #include #include #include namespace Libs::Graphics { class CommandBuffer; struct GraphicContext; struct VulkanBuffer; struct VulkanImage; struct DepthStencilVulkanImage; struct VulkanSwapchain; struct BufferImageCopy { uint32_t offset; uint32_t pitch; uint32_t dst_level; uint32_t width; uint32_t height; uint32_t copy_height = 0; uint32_t dst_layer = 0; int dst_x; int dst_y; int dst_z = 0; vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor; }; struct ImageBufferCopy { uint32_t offset; uint32_t pitch; uint32_t src_level; uint32_t width; uint32_t height; uint32_t copy_height = 0; uint32_t src_layer = 0; int src_x; int src_y; int src_z = 0; vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor; }; struct ImageImageCopy { explicit ImageImageCopy(VulkanImage& source): src_image(source) {} VulkanImage& src_image; uint32_t src_level = 0; uint32_t dst_level = 0; uint32_t width = 0; uint32_t height = 0; uint32_t src_layer = 0; uint32_t dst_layer = 0; vk::ImageAspectFlags src_aspect = vk::ImageAspectFlagBits::eColor; vk::ImageAspectFlags dst_aspect = vk::ImageAspectFlagBits::eColor; int src_x = 0; int src_y = 0; int src_z = 0; int dst_x = 0; int dst_y = 0; int dst_z = 0; }; namespace Transfer { [[nodiscard]] std::vector MakeLayeredImageBufferCopies(uint32_t layers, uint64_t slice_size, uint32_t pitch, uint32_t width, uint32_t height, vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor); enum class StagingBufferType { Texture, Vertex, ReadBack }; using DownloadedImageConsumer = std::function)>; class ScratchBuffer { public: explicit ScratchBuffer(uint64_t size); ~ScratchBuffer(); KYTY_CLASS_NO_COPY(ScratchBuffer); [[nodiscard]] void* Data() const { return m_data; } private: void* m_data = nullptr; }; void CopyImage(CommandBuffer& buffer, std::span regions, VulkanImage& dst_image, vk::ImageLayout dst_layout); void CopyImageViaBuffer(CommandBuffer& buffer, VulkanImage& src_image, vk::ImageAspectFlags src_aspect, VulkanImage& dst_image, vk::ImageAspectFlags dst_aspect, uint32_t bytes_per_element, vk::ImageLayout dst_layout); void BlitToSwapchain(CommandBuffer& buffer, VulkanImage& src_image, VulkanSwapchain& dst_swapchain); void ClearColorImage(CommandBuffer& buffer, VulkanImage& image, const vk::ClearColorValue& color); void UploadImage(VulkanImage& dst_image, const void* src_data, uint64_t size, uint32_t src_pitch, vk::ImageLayout dst_layout); void UploadImage(DepthStencilVulkanImage& dst_image, const void* src_data, uint64_t size, uint32_t src_pitch, vk::ImageAspectFlags aspect); void UploadImage(VulkanImage& dst_image, const void* src_data, uint64_t size, std::span regions, vk::ImageLayout dst_layout); void UploadTiledImage(VulkanImage& dst_image, const void* tiled_data, uint64_t tiled_size, uint64_t linear_size, std::span infos, std::span regions, vk::ImageLayout dst_layout); void CopyImageImmediate(std::span regions, VulkanImage& dst_image, vk::ImageLayout dst_layout); void DownloadImage(void* dst_data, uint64_t size, uint32_t dst_pitch, VulkanImage& src_image, vk::ImageLayout src_layout, vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor); void DownloadImage(void* dst_data, uint64_t size, std::span regions, VulkanImage& src_image, vk::ImageLayout src_layout); // Invokes consumer synchronously after the image copy fence while the readback staging buffer is // reserved. The supplied span is valid only for the call; the consumer must not retain it or // re-enter Transfer. void ProcessDownloadedImage(uint64_t size, std::span regions, VulkanImage& src_image, vk::ImageLayout src_layout, const DownloadedImageConsumer& consumer); void DownloadTiledImage(void* tiled_data, uint64_t tiled_size, uint64_t linear_size, std::span infos, std::span regions, VulkanImage& src_image, vk::ImageLayout src_layout); void UploadBuffer(StagingBufferType type, VulkanBuffer& dst_buffer, uint64_t dst_offset, const void* src_data, uint64_t size); void CopyBuffer(VulkanBuffer& src_buffer, VulkanBuffer& dst_buffer, uint64_t size); void DownloadBuffer(VulkanBuffer& src_buffer, uint64_t src_offset, void* dst_data, uint64_t size); void ReleaseCachedResources(); bool GuestBufferIsTiled(uint64_t vaddr, uint64_t size); bool IsBlockCompressedFormat(vk::Format format); uint32_t BlockCompressedBytesPerBlock(vk::Format format); void WaitForGraphicsIdle(); inline std::pair MipmapAtlasOffset(uint32_t lod, uint32_t width, uint32_t height) { uint32_t mip_width = width; uint32_t mip_height = height; int mip_x = 0; int mip_y = 0; for (uint32_t i = 0; i < 16; i++) { if (i == lod) { return {mip_x, mip_y}; } bool odd = ((i & 1u) != 0); mip_x += static_cast(odd ? mip_width : 0); mip_y += static_cast(odd ? 0 : mip_height); mip_width >>= (mip_width > 1 ? 1u : 0u); mip_height >>= (mip_height > 1 ? 1u : 0u); } return {mip_x, mip_y}; } } // namespace Transfer } // namespace Libs::Graphics #endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_TRANSFER_H_