2024-04-14 16:09:51 +02:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "common/enum.h"
|
|
|
|
#include "common/types.h"
|
|
|
|
#include "core/libraries/videoout/buffer.h"
|
2024-05-25 14:33:15 +02:00
|
|
|
#include "video_core/amdgpu/liverpool.h"
|
2024-05-27 00:07:46 +02:00
|
|
|
#include "video_core/amdgpu/resource.h"
|
2024-04-14 16:09:51 +02:00
|
|
|
#include "video_core/renderer_vulkan/vk_common.h"
|
2024-05-22 00:35:12 +02:00
|
|
|
#include "video_core/texture_cache/image_view.h"
|
2024-04-14 16:09:51 +02:00
|
|
|
#include "video_core/texture_cache/types.h"
|
|
|
|
|
|
|
|
namespace Vulkan {
|
|
|
|
class Instance;
|
|
|
|
class Scheduler;
|
|
|
|
} // namespace Vulkan
|
|
|
|
|
|
|
|
VK_DEFINE_HANDLE(VmaAllocation)
|
|
|
|
VK_DEFINE_HANDLE(VmaAllocator)
|
|
|
|
|
|
|
|
namespace VideoCore {
|
|
|
|
|
|
|
|
enum ImageFlagBits : u32 {
|
|
|
|
CpuModified = 1 << 2, ///< Contents have been modified from the CPU
|
|
|
|
GpuModified = 1 << 3, ///< Contents have been modified from the GPU
|
|
|
|
Tracked = 1 << 4, ///< Writes and reads are being hooked from the CPU
|
|
|
|
Registered = 1 << 6, ///< True when the image is registered
|
|
|
|
Picked = 1 << 7, ///< Temporary flag to mark the image as picked
|
|
|
|
};
|
|
|
|
DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
|
|
|
|
|
|
|
|
struct ImageInfo {
|
|
|
|
ImageInfo() = default;
|
|
|
|
explicit ImageInfo(const Libraries::VideoOut::BufferAttributeGroup& group) noexcept;
|
2024-05-25 14:33:15 +02:00
|
|
|
explicit ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer) noexcept;
|
2024-05-27 00:07:46 +02:00
|
|
|
explicit ImageInfo(const AmdGpu::Image& image) noexcept;
|
2024-04-14 16:09:51 +02:00
|
|
|
|
|
|
|
bool is_tiled = false;
|
|
|
|
vk::Format pixel_format = vk::Format::eUndefined;
|
|
|
|
vk::ImageType type = vk::ImageType::e1D;
|
|
|
|
SubresourceExtent resources;
|
|
|
|
Extent3D size{1, 1, 1};
|
2024-04-29 14:16:42 +02:00
|
|
|
u32 pitch = 0;
|
|
|
|
u32 guest_size_bytes = 0;
|
2024-04-14 16:09:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct UniqueImage {
|
|
|
|
explicit UniqueImage(vk::Device device, VmaAllocator allocator);
|
|
|
|
~UniqueImage();
|
|
|
|
|
|
|
|
UniqueImage(const UniqueImage&) = delete;
|
|
|
|
UniqueImage& operator=(const UniqueImage&) = delete;
|
|
|
|
|
2024-05-29 17:17:24 +02:00
|
|
|
UniqueImage(UniqueImage&& other)
|
|
|
|
: image{std::exchange(other.image, VK_NULL_HANDLE)},
|
|
|
|
allocator{std::exchange(other.allocator, VK_NULL_HANDLE)},
|
|
|
|
allocation{std::exchange(other.allocation, VK_NULL_HANDLE)} {}
|
2024-04-14 16:09:51 +02:00
|
|
|
UniqueImage& operator=(UniqueImage&& other) {
|
|
|
|
image = std::exchange(other.image, VK_NULL_HANDLE);
|
2024-05-29 17:17:24 +02:00
|
|
|
allocator = std::exchange(other.allocator, VK_NULL_HANDLE);
|
|
|
|
allocation = std::exchange(other.allocation, VK_NULL_HANDLE);
|
2024-04-14 16:09:51 +02:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Create(const vk::ImageCreateInfo& image_ci);
|
|
|
|
|
|
|
|
operator vk::Image() const {
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
vk::Device device;
|
|
|
|
VmaAllocator allocator;
|
|
|
|
VmaAllocation allocation;
|
|
|
|
vk::Image image{};
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Image {
|
|
|
|
explicit Image(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler,
|
|
|
|
const ImageInfo& info, VAddr cpu_addr);
|
|
|
|
~Image();
|
|
|
|
|
|
|
|
Image(const Image&) = delete;
|
|
|
|
Image& operator=(const Image&) = delete;
|
|
|
|
|
|
|
|
Image(Image&&) = default;
|
|
|
|
Image& operator=(Image&&) = default;
|
|
|
|
|
|
|
|
[[nodiscard]] bool Overlaps(VAddr overlap_cpu_addr, size_t overlap_size) const noexcept {
|
|
|
|
const VAddr overlap_end = overlap_cpu_addr + overlap_size;
|
|
|
|
return cpu_addr < overlap_end && overlap_cpu_addr < cpu_addr_end;
|
|
|
|
}
|
|
|
|
|
2024-05-22 00:35:12 +02:00
|
|
|
ImageViewId FindView(const ImageViewInfo& info) const {
|
|
|
|
const auto it = std::ranges::find(image_view_infos, info);
|
|
|
|
if (it == image_view_infos.end()) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return image_view_ids[std::distance(it, image_view_infos.begin())];
|
|
|
|
}
|
|
|
|
|
2024-05-17 12:44:07 +02:00
|
|
|
void Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask);
|
|
|
|
|
2024-04-14 16:09:51 +02:00
|
|
|
const Vulkan::Instance* instance;
|
|
|
|
Vulkan::Scheduler* scheduler;
|
|
|
|
ImageInfo info;
|
|
|
|
UniqueImage image;
|
2024-05-17 12:44:07 +02:00
|
|
|
vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor;
|
2024-04-14 16:09:51 +02:00
|
|
|
ImageFlagBits flags = ImageFlagBits::CpuModified;
|
|
|
|
VAddr cpu_addr = 0;
|
|
|
|
VAddr cpu_addr_end = 0;
|
2024-05-22 00:35:12 +02:00
|
|
|
std::vector<ImageViewInfo> image_view_infos;
|
|
|
|
std::vector<ImageViewId> image_view_ids;
|
2024-05-17 12:44:07 +02:00
|
|
|
|
|
|
|
// Resource state tracking
|
|
|
|
vk::Flags<vk::PipelineStageFlagBits> pl_stage = vk::PipelineStageFlagBits::eAllCommands;
|
|
|
|
vk::Flags<vk::AccessFlagBits> access_mask = vk::AccessFlagBits::eNone;
|
|
|
|
vk::ImageLayout layout = vk::ImageLayout::eUndefined;
|
2024-04-14 16:09:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace VideoCore
|