mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 14:09:58 +00:00
Port UMA part 2
This commit is contained in:
@@ -283,11 +283,13 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
|
||||
[[nodiscard]] vk::Image MakeImage(const Device& device, const MemoryAllocator& allocator,
|
||||
const ImageInfo& info, std::span<const VkFormat> view_formats,
|
||||
std::optional<VkFormat> format_override = {}) {
|
||||
std::optional<VkFormat> format_override = {},
|
||||
VkImageUsageFlags host_usage = 0) {
|
||||
if (info.type == ImageType::Buffer) {
|
||||
return vk::Image{};
|
||||
}
|
||||
VkImageCreateInfo image_ci = MakeImageCreateInfo(device, info, format_override);
|
||||
image_ci.usage |= host_usage;
|
||||
const VkImageFormatListCreateInfo image_format_list = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
@@ -1042,6 +1044,17 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
|
||||
pitch_unswizzle_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
|
||||
compute_pass_descriptor_queue);
|
||||
}
|
||||
for (size_t index = 0; index < VideoCore::Surface::MaxPixelFormat; index++) {
|
||||
const auto format = static_cast<PixelFormat>(index);
|
||||
if (!device.IsHostImageCopySupported() || DefaultBlockWidth(format) == 1) {
|
||||
continue;
|
||||
}
|
||||
const VkFormat vk_format =
|
||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format).format;
|
||||
host_copy_formats[index] =
|
||||
(device.GetPhysical().GetFormatProperties3(vk_format).optimalTilingFeatures &
|
||||
VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) != 0;
|
||||
}
|
||||
if (!device.IsKhrImageFormatListSupported()) {
|
||||
return;
|
||||
}
|
||||
@@ -1968,10 +1981,7 @@ void TextureCacheRuntime::TickFrame() {
|
||||
Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu_addr_,
|
||||
VAddr cpu_addr_)
|
||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime_.scheduler},
|
||||
runtime{&runtime_},
|
||||
original_image(MakeImage(runtime_.device, runtime_.memory_allocator, info,
|
||||
runtime->ViewFormats(info.format))),
|
||||
aspect_mask(ImageAspectMask(info.format)) {
|
||||
runtime{&runtime_}, aspect_mask(ImageAspectMask(info.format)) {
|
||||
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
|
||||
switch (Settings::values.accelerate_astc.GetValue()) {
|
||||
case Settings::AstcDecodeMode::Gpu:
|
||||
@@ -1997,6 +2007,13 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
|
||||
WillUseAcceleratedUnswizzle(runtime->device, info)) {
|
||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||
}
|
||||
VkImageUsageFlags host_usage{};
|
||||
if (False(flags & VideoCommon::ImageFlagBits::Converted) &&
|
||||
runtime->host_copy_formats[static_cast<size_t>(info.format)]) {
|
||||
host_usage = VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
|
||||
}
|
||||
original_image = MakeImage(runtime->device, runtime->memory_allocator, info,
|
||||
runtime->ViewFormats(info.format), {}, host_usage);
|
||||
if (runtime->device.HasDebuggingToolAttached()) {
|
||||
original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
|
||||
}
|
||||
@@ -2130,6 +2147,33 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag
|
||||
UploadMemory(map.buffer, map.offset, copies);
|
||||
}
|
||||
|
||||
void Image::UploadHostMemory(std::span<const u8> memory,
|
||||
std::span<const BufferImageCopy> copies) {
|
||||
const auto vk_copies = TransformBufferImageCopies(copies, 0, aspect_mask);
|
||||
boost::container::small_vector<VkMemoryToImageCopyEXT, 16> regions;
|
||||
for (const VkBufferImageCopy2& copy : vk_copies) {
|
||||
regions.push_back(VkMemoryToImageCopyEXT{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
|
||||
.pNext = nullptr,
|
||||
.pHostPointer = memory.data() + copy.bufferOffset,
|
||||
.memoryRowLength = copy.bufferRowLength,
|
||||
.memoryImageHeight = copy.bufferImageHeight,
|
||||
.imageSubresource = copy.imageSubresource,
|
||||
.imageOffset = copy.imageOffset,
|
||||
.imageExtent = copy.imageExtent,
|
||||
});
|
||||
}
|
||||
runtime->device.GetLogical().CopyMemoryToImageEXT(VkCopyMemoryToImageInfoEXT{
|
||||
.sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.dstImage = *original_image,
|
||||
.dstImageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.regionCount = static_cast<u32>(regions.size()),
|
||||
.pRegions = regions.data(),
|
||||
});
|
||||
}
|
||||
|
||||
void Image::DownloadMemory(VkBuffer buffer, size_t offset,
|
||||
std::span<const VideoCommon::BufferImageCopy> copies) {
|
||||
std::array buffer_handles{
|
||||
@@ -3177,9 +3221,27 @@ void TextureCacheRuntime::AccelerateImageUpload(
|
||||
}
|
||||
|
||||
void TextureCacheRuntime::TransitionImageLayout(Image& image) {
|
||||
if (!image.ExchangeInitialization()) {
|
||||
RecordInitialLayout(scheduler, image.Handle(), image.AspectMask());
|
||||
if (image.ExchangeInitialization()) {
|
||||
return;
|
||||
}
|
||||
if (!image.CanUploadHostMemory()) {
|
||||
RecordInitialLayout(scheduler, image.Handle(), image.AspectMask());
|
||||
return;
|
||||
}
|
||||
device.GetLogical().TransitionImageLayoutEXT(VkHostImageLayoutTransitionInfoEXT{
|
||||
.sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.image = image.Handle(),
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.subresourceRange{
|
||||
.aspectMask = image.AspectMask(),
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <span>
|
||||
|
||||
#include "video_core/texture_cache/texture_cache_base.h"
|
||||
@@ -154,6 +155,7 @@ public:
|
||||
std::optional<PitchUnswizzlePass> pitch_unswizzle_pass;
|
||||
const Settings::ResolutionScalingInfo& resolution;
|
||||
std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats;
|
||||
std::bitset<VideoCore::Surface::MaxPixelFormat> host_copy_formats;
|
||||
|
||||
static constexpr size_t indexing_slots = 8 * sizeof(size_t);
|
||||
std::array<vk::Buffer, indexing_slots> buffers{};
|
||||
@@ -294,6 +296,13 @@ public:
|
||||
void UploadMemory(const StagingBufferRef& map,
|
||||
std::span<const VideoCommon::BufferImageCopy> copies);
|
||||
|
||||
void UploadHostMemory(std::span<const u8> memory,
|
||||
std::span<const VideoCommon::BufferImageCopy> copies);
|
||||
|
||||
[[nodiscard]] bool CanUploadHostMemory() const noexcept {
|
||||
return (original_image.UsageFlags() & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) != 0;
|
||||
}
|
||||
|
||||
void DownloadMemory(VkBuffer buffer, size_t offset,
|
||||
std::span<const VideoCommon::BufferImageCopy> copies);
|
||||
|
||||
|
||||
@@ -1033,6 +1033,18 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
|
||||
QueueAsyncDecode(image, image_id);
|
||||
return;
|
||||
}
|
||||
if constexpr (requires { image.UploadHostMemory(unswizzle_data_buffer, {}); }) {
|
||||
if (True(image.flags & ImageFlagBits::ReorderableUpload) && image.CanUploadHostMemory()) {
|
||||
Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::UnsafeRead>
|
||||
swizzle_data(*gpu_memory, image.gpu_addr, image.guest_size_bytes,
|
||||
&swizzle_data_buffer);
|
||||
unswizzle_data_buffer.resize_destructive(image.unswizzled_size_bytes);
|
||||
const auto copies = FixSmallVectorADL(UnswizzleImage(
|
||||
*gpu_memory, image.gpu_addr, image.info, swizzle_data, unswizzle_data_buffer));
|
||||
image.UploadHostMemory(unswizzle_data_buffer, copies);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto staging = runtime.UploadStagingBuffer(MapSizeBytes(image));
|
||||
UploadImageContents(image, staging);
|
||||
|
||||
@@ -433,6 +433,13 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
const vk::InstanceDispatch& dld_)
|
||||
: instance{instance_}, dld{dld_}, physical{physical_},
|
||||
format_properties(GetFormatProperties(physical)) {
|
||||
const VkPhysicalDeviceMemoryProperties memory_properties =
|
||||
physical.GetMemoryProperties().memoryProperties;
|
||||
is_uma = std::all_of(memory_properties.memoryTypes,
|
||||
memory_properties.memoryTypes + memory_properties.memoryTypeCount,
|
||||
[](const VkMemoryType& type) {
|
||||
return (type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0;
|
||||
});
|
||||
// Get suitability and device properties.
|
||||
const bool is_suitable = GetSuitability(surface != VkSurfaceKHR{});
|
||||
|
||||
@@ -487,15 +494,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
properties.subgroup_size_control.maxSubgroupSize > GuestWarpSize;
|
||||
|
||||
is_integrated = properties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
|
||||
const VkPhysicalDeviceMemoryProperties memory_properties =
|
||||
physical.GetMemoryProperties().memoryProperties;
|
||||
is_uma = std::all_of(memory_properties.memoryTypes,
|
||||
memory_properties.memoryTypes + memory_properties.memoryTypeCount,
|
||||
[](const VkMemoryType& type) {
|
||||
return (type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ==
|
||||
0 ||
|
||||
(type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
|
||||
});
|
||||
|
||||
supports_d24_depth =
|
||||
IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
@@ -1425,6 +1423,12 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.maintenance5, features.maintenance5,
|
||||
VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
|
||||
|
||||
if (!is_uma || instance_version < VK_API_VERSION_1_3 ||
|
||||
!features.host_image_copy.hostImageCopy) {
|
||||
RemoveExtensionFeature(extensions.host_image_copy, features.host_image_copy,
|
||||
VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
|
||||
extensions.synchronization2 = features.synchronization2.synchronization2;
|
||||
extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering;
|
||||
|
||||
@@ -68,6 +68,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \
|
||||
FEATURE(EXT, ExtendedDynamicState3, EXTENDED_DYNAMIC_STATE_3, extended_dynamic_state3) \
|
||||
FEATURE(EXT, 4444Formats, 4444_FORMATS, format_a4b4g4r4) \
|
||||
FEATURE(EXT, HostImageCopy, HOST_IMAGE_COPY, host_image_copy) \
|
||||
FEATURE(EXT, IndexTypeUint8, INDEX_TYPE_UINT8, index_type_uint8) \
|
||||
FEATURE(EXT, LineRasterization, LINE_RASTERIZATION, line_rasterization) \
|
||||
FEATURE(EXT, PrimitiveTopologyListRestart, PRIMITIVE_TOPOLOGY_LIST_RESTART, \
|
||||
@@ -988,6 +989,10 @@ FN_MAX_LIMIT_LIST
|
||||
return is_uma;
|
||||
}
|
||||
|
||||
bool IsHostImageCopySupported() const {
|
||||
return extensions.host_image_copy;
|
||||
}
|
||||
|
||||
bool HasNullDescriptor() const {
|
||||
return features.robustness2.nullDescriptor;
|
||||
}
|
||||
|
||||
@@ -206,6 +206,8 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||
X(vkGetPipelineExecutablePropertiesKHR);
|
||||
X(vkGetPipelineExecutableStatisticsKHR);
|
||||
X(vkGetSemaphoreCounterValue);
|
||||
X(vkCopyMemoryToImageEXT);
|
||||
X(vkTransitionImageLayoutEXT);
|
||||
X(vkQueueBindSparse);
|
||||
X(vkQueueSubmit2);
|
||||
X(vkResetFences);
|
||||
|
||||
@@ -355,6 +355,8 @@ struct DeviceDispatch : InstanceDispatch {
|
||||
PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{};
|
||||
PFN_vkGetQueryPoolResults vkGetQueryPoolResults{};
|
||||
PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{};
|
||||
PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT{};
|
||||
PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT{};
|
||||
PFN_vkQueueBindSparse vkQueueBindSparse{};
|
||||
PFN_vkQueueSubmit2 vkQueueSubmit2{};
|
||||
PFN_vkResetFences vkResetFences{};
|
||||
@@ -1092,6 +1094,14 @@ public:
|
||||
dld->vkResetQueryPool(handle, query_pool, first, count);
|
||||
}
|
||||
|
||||
void CopyMemoryToImageEXT(const VkCopyMemoryToImageInfoEXT& info) const {
|
||||
Check(dld->vkCopyMemoryToImageEXT(handle, &info));
|
||||
}
|
||||
|
||||
void TransitionImageLayoutEXT(const VkHostImageLayoutTransitionInfoEXT& info) const {
|
||||
Check(dld->vkTransitionImageLayoutEXT(handle, 1, &info));
|
||||
}
|
||||
|
||||
VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size,
|
||||
void* data, VkDeviceSize stride,
|
||||
VkQueryResultFlags flags) const noexcept {
|
||||
|
||||
Reference in New Issue
Block a user