mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-27 17:31:31 +00:00
Extended the impact on AHB fallback
This commit is contained in:
@@ -700,7 +700,11 @@ public:
|
||||
constexpr u64 MapSlotsPerWindow = 64;
|
||||
const u64 affordable_windows = permissible_maps / MapSlotsPerWindow;
|
||||
budget = (std::min)(budget, affordable_windows * window_size);
|
||||
budget = (std::min)(budget, static_cast<u64>(backing_size) / 2);
|
||||
const u64 available = Common::GetAvailablePhysicalMemory();
|
||||
if (available != 0) {
|
||||
budget = (std::min)(budget, available / 2);
|
||||
}
|
||||
budget = (std::min)(budget, static_cast<u64>(backing_size));
|
||||
budget = Common::AlignDown(budget, window_size);
|
||||
constexpr u64 MinimumBudget = 256ULL << 20;
|
||||
if (budget < MinimumBudget) {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "common/memory_detect.h"
|
||||
|
||||
@@ -97,4 +98,39 @@ u64 GetPermissibleMapCount() {
|
||||
return count - ReservedMaps;
|
||||
}
|
||||
|
||||
u64 GetAvailablePhysicalMemory() {
|
||||
#ifdef _WIN32
|
||||
MEMORYSTATUSEX memorystatus;
|
||||
memorystatus.dwLength = sizeof(memorystatus);
|
||||
if (GlobalMemoryStatusEx(&memorystatus) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return memorystatus.ullAvailPhys;
|
||||
#elif defined(__linux__)
|
||||
static constexpr char AvailableKey[] = "MemAvailable:";
|
||||
if (std::FILE* const file = std::fopen("/proc/meminfo", "re")) {
|
||||
char line[256];
|
||||
u64 available = 0;
|
||||
while (std::fgets(line, sizeof(line), file) != nullptr) {
|
||||
if (std::strncmp(line, AvailableKey, sizeof(AvailableKey) - 1) != 0) {
|
||||
continue;
|
||||
}
|
||||
available = std::strtoull(line + sizeof(AvailableKey) - 1, nullptr, 10) * 1024;
|
||||
break;
|
||||
}
|
||||
std::fclose(file);
|
||||
if (available != 0) {
|
||||
return available;
|
||||
}
|
||||
}
|
||||
struct sysinfo meminfo;
|
||||
if (sysinfo(&meminfo) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<u64>(meminfo.freeram) * static_cast<u64>(meminfo.mem_unit);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -23,4 +23,6 @@ struct MemoryInfo {
|
||||
|
||||
[[nodiscard]] u64 GetPermissibleMapCount();
|
||||
|
||||
[[nodiscard]] u64 GetAvailablePhysicalMemory();
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/div_ceil.h"
|
||||
@@ -992,6 +993,31 @@ void BlockLinearUnswizzle2DPass::UnswizzleFrom(
|
||||
const u32 layers = image.info.resources.layers;
|
||||
const VkImageAspectFlags aspect = image.AspectMask();
|
||||
|
||||
const VkDeviceSize output_alignment =
|
||||
(std::max)(device.GetStorageBufferAlignment(), VkDeviceSize{16});
|
||||
VkDeviceSize total_output = 0;
|
||||
for (const VideoCommon::SwizzleParameters& sw : swizzles) {
|
||||
const auto params =
|
||||
VideoCommon::Accelerated::MakeBlockLinearSwizzle2DParams(sw, image.info);
|
||||
const VkDeviceSize level_size = static_cast<VkDeviceSize>(sw.num_tiles.width) *
|
||||
sw.num_tiles.height * layers *
|
||||
(1ULL << params.bytes_per_block_log2);
|
||||
if (level_size == 0) {
|
||||
continue;
|
||||
}
|
||||
total_output = Common::AlignUp(total_output, output_alignment) + level_size;
|
||||
}
|
||||
if (total_output == 0) {
|
||||
return;
|
||||
}
|
||||
const StagingBufferRef output =
|
||||
staging_buffer_pool.Request(static_cast<size_t>(total_output), MemoryUsage::DeviceLocal);
|
||||
const VkBuffer out_buffer = output.buffer;
|
||||
if (out_buffer == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
VkDeviceSize level_offset = 0;
|
||||
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
|
||||
VkAccessFlags pre_access = VK_ACCESS_NONE;
|
||||
@@ -1040,8 +1066,9 @@ void BlockLinearUnswizzle2DPass::UnswizzleFrom(
|
||||
const u32 texel_width = (std::max)(1u, image.info.size.width >> level);
|
||||
const u32 texel_height = (std::max)(1u, image.info.size.height >> level);
|
||||
|
||||
const StagingBufferRef output =
|
||||
staging_buffer_pool.Request(static_cast<size_t>(output_size), MemoryUsage::DeviceLocal);
|
||||
level_offset = Common::AlignUp(level_offset, output_alignment);
|
||||
const VkDeviceSize out_offset = output.offset + level_offset;
|
||||
level_offset += output_size;
|
||||
|
||||
BlockLinearUnswizzle2DPushConstants pc{};
|
||||
pc.dim = {width, height, layers};
|
||||
@@ -1056,22 +1083,17 @@ void BlockLinearUnswizzle2DPass::UnswizzleFrom(
|
||||
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
||||
compute_pass_descriptor_queue.AddBuffer(source_buffer, sw.buffer_offset + source_offset,
|
||||
image.guest_size_bytes - sw.buffer_offset);
|
||||
compute_pass_descriptor_queue.AddBuffer(output.buffer, output.offset, output_size);
|
||||
compute_pass_descriptor_queue.AddBuffer(out_buffer, out_offset, output_size);
|
||||
|
||||
const void* descriptor_data = compute_pass_descriptor_queue.UpdateData();
|
||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||
|
||||
const u32 gx = Common::DivCeil(width, 16u);
|
||||
const u32 gy = Common::DivCeil(height, 8u);
|
||||
const VkBuffer out_buffer = output.buffer;
|
||||
const VkDeviceSize out_offset = output.offset;
|
||||
|
||||
scheduler.Record([this, set, descriptor_data, pc, gx, gy, layers, output_size, out_buffer,
|
||||
out_offset, dst_image, aspect, texel_width, texel_height,
|
||||
level](vk::CommandBuffer cmdbuf) {
|
||||
if (out_buffer == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
||||
|
||||
@@ -490,13 +490,29 @@ namespace Vulkan {
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
|
||||
const bool want_address = device.IsBufferDeviceAddressSupported();
|
||||
VkBufferUsageFlags minimal_usage = TransferUsage | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
if (want_address) {
|
||||
shader_usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
minimal_usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
}
|
||||
|
||||
const auto reset_windows = [&] {
|
||||
for (Window &window : windows) {
|
||||
if (window.buffer != VK_NULL_HANDLE) {
|
||||
logical.DestroyBufferRaw(window.buffer);
|
||||
}
|
||||
}
|
||||
windows.clear();
|
||||
imported_size = 0;
|
||||
};
|
||||
|
||||
bindable = import_all(shader_usage, want_address);
|
||||
if (!bindable) {
|
||||
imported_size = 0;
|
||||
reset_windows();
|
||||
bindable = import_all(minimal_usage, want_address);
|
||||
}
|
||||
if (!bindable) {
|
||||
reset_windows();
|
||||
import_all(TransferUsage, false);
|
||||
}
|
||||
if (windows.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user