video: Import new shader recompiler + display a triangle (#142)

This commit is contained in:
TheTurtle 2024-05-22 01:35:12 +03:00 committed by GitHub
parent 8cf64a33b2
commit 8730968385
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
103 changed files with 17793 additions and 729 deletions

View file

@ -38,7 +38,7 @@ using Libraries::VideoOut::TilingMode;
if (false /*&& IsDepthStencilFormat(format)*/) {
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
} else {
// usage |= vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage;
usage |= vk::ImageUsageFlagBits::eColorAttachment;
}
return usage;
}

View file

@ -7,6 +7,7 @@
#include "common/types.h"
#include "core/libraries/videoout/buffer.h"
#include "video_core/renderer_vulkan/vk_common.h"
#include "video_core/texture_cache/image_view.h"
#include "video_core/texture_cache/types.h"
namespace Vulkan {
@ -41,23 +42,6 @@ struct ImageInfo {
u32 guest_size_bytes = 0;
};
struct Handle {
VmaAllocation allocation;
VkImage image;
Handle() = default;
Handle(Handle&& other)
: image{std::exchange(other.image, VK_NULL_HANDLE)},
allocation{std::exchange(other.allocation, VK_NULL_HANDLE)} {}
Handle& operator=(Handle&& other) {
image = std::exchange(other.image, VK_NULL_HANDLE);
allocation = std::exchange(other.allocation, VK_NULL_HANDLE);
return *this;
}
};
struct UniqueImage {
explicit UniqueImage(vk::Device device, VmaAllocator allocator);
~UniqueImage();
@ -100,6 +84,14 @@ struct Image {
return cpu_addr < overlap_end && overlap_cpu_addr < cpu_addr_end;
}
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())];
}
void Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask);
const Vulkan::Instance* instance;
@ -110,6 +102,8 @@ struct Image {
ImageFlagBits flags = ImageFlagBits::CpuModified;
VAddr cpu_addr = 0;
VAddr cpu_addr_end = 0;
std::vector<ImageViewInfo> image_view_infos;
std::vector<ImageViewId> image_view_ids;
// Resource state tracking
vk::Flags<vk::PipelineStageFlagBits> pl_stage = vk::PipelineStageFlagBits::eAllCommands;

View file

@ -13,20 +13,9 @@ class Scheduler;
namespace VideoCore {
enum class ImageViewType : u32 {
e1D,
e2D,
Cube,
e3D,
e1DArray,
e2DArray,
CubeArray,
Buffer,
};
struct ImageViewInfo {
vk::ImageViewType type{};
vk::Format format{};
vk::ImageViewType type = vk::ImageViewType::e2D;
vk::Format format = vk::Format::eR8G8B8A8Unorm;
SubresourceRange range;
vk::ComponentMapping mapping{};

View file

@ -31,10 +31,6 @@ class SlotVector {
constexpr static std::size_t InitialCapacity = 1024;
public:
SlotVector() {
Reserve(InitialCapacity);
}
~SlotVector() noexcept {
std::size_t index = 0;
for (u64 bits : stored_bitset) {

View file

@ -83,6 +83,15 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
ASSERT_MSG(veh_handle, "Failed to register an exception handler");
#endif
g_texture_cache = this;
ImageInfo info;
info.pixel_format = vk::Format::eR8G8B8A8Unorm;
info.type = vk::ImageType::e2D;
const ImageId null_id = slot_images.insert(instance, scheduler, info, 0);
ASSERT(null_id.index == 0);
ImageViewInfo view_info;
void(slot_image_views.insert(instance, scheduler, view_info, slot_images[null_id].image));
}
TextureCache::~TextureCache() {
@ -128,6 +137,29 @@ Image& TextureCache::FindImage(const ImageInfo& info, VAddr cpu_address) {
return image;
}
ImageView& TextureCache::RenderTarget(VAddr cpu_address, u32 pitch) {
boost::container::small_vector<ImageId, 2> image_ids;
ForEachImageInRegion(cpu_address, pitch * 4, [&](ImageId image_id, Image& image) {
if (image.cpu_addr == cpu_address) {
image_ids.push_back(image_id);
}
});
ASSERT_MSG(image_ids.size() <= 1, "Overlapping framebuffers not allowed!");
auto* image = &slot_images[image_ids.empty() ? ImageId{0} : image_ids.back()];
ImageViewInfo info;
info.format = vk::Format::eB8G8R8A8Srgb;
if (const ImageViewId view_id = image->FindView(info); view_id) {
return slot_image_views[view_id];
}
const ImageViewId view_id = slot_image_views.insert(instance, scheduler, info, image->image);
image->image_view_infos.emplace_back(info);
image->image_view_ids.emplace_back(view_id);
return slot_image_views[view_id];
}
void TextureCache::RefreshImage(Image& image) {
// Mark image as validated.
image.flags &= ~ImageFlagBits::CpuModified;

View file

@ -9,6 +9,7 @@
#include "video_core/renderer_vulkan/vk_stream_buffer.h"
#include "video_core/texture_cache/image.h"
#include "video_core/texture_cache/image_view.h"
#include "video_core/texture_cache/slot_vector.h"
namespace Core::Libraries::VideoOut {
@ -35,6 +36,9 @@ public:
/// Retrieves the image handle of the image with the provided attributes and address.
Image& FindImage(const ImageInfo& info, VAddr cpu_address);
/// Retrieves the render target with specified properties
ImageView& RenderTarget(VAddr cpu_address, u32 pitch);
/// Reuploads image contents.
void RefreshImage(Image& image);
@ -116,6 +120,7 @@ private:
Vulkan::Scheduler& scheduler;
Vulkan::StreamBuffer staging;
SlotVector<Image> slot_images;
SlotVector<ImageView> slot_image_views;
tsl::robin_pg_map<u64, std::vector<ImageId>> page_table;
boost::icl::interval_map<VAddr, s32> cached_pages;
#ifdef _WIN64

View file

@ -47,16 +47,22 @@ struct SubresourceLayers {
struct SubresourceBase {
s32 level = 0;
s32 layer = 0;
auto operator<=>(const SubresourceBase&) const = default;
};
struct SubresourceExtent {
s32 levels = 1;
s32 layers = 1;
auto operator<=>(const SubresourceExtent&) const = default;
};
struct SubresourceRange {
SubresourceBase base;
SubresourceExtent extent;
auto operator<=>(const SubresourceRange&) const = default;
};
struct ImageCopy {