summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/CMakeLists.txt6
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp31
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp24
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp8
-rw-r--r--src/video_core/texture_cache/util.cpp77
-rw-r--r--src/video_core/textures/astc.cpp5
-rw-r--r--src/video_core/textures/bcn.cpp87
-rw-r--r--src/video_core/textures/bcn.h17
-rw-r--r--src/video_core/textures/workers.cpp15
-rw-r--r--src/video_core/textures/workers.h12
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp6
12 files changed, 264 insertions, 26 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index a0009a36f..308d013d6 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -246,10 +246,14 @@ add_library(video_core STATIC
texture_cache/util.h
textures/astc.h
textures/astc.cpp
+ textures/bcn.cpp
+ textures/bcn.h
textures/decoders.cpp
textures/decoders.h
textures/texture.cpp
textures/texture.h
+ textures/workers.cpp
+ textures/workers.h
transform_feedback.cpp
transform_feedback.h
video_core.cpp
@@ -275,7 +279,7 @@ add_library(video_core STATIC
create_target_directory_groups(video_core)
target_link_libraries(video_core PUBLIC common core)
-target_link_libraries(video_core PUBLIC glad shader_recompiler)
+target_link_libraries(video_core PUBLIC glad shader_recompiler stb)
if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32)
add_dependencies(video_core ffmpeg-build)
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 98756e4da..f2508fbf0 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1664,7 +1664,7 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s
// cbufs, which do not store the sizes adjacent to the addresses, so use the fully
// mapped buffer size for now.
const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
- return memory_layout_size;
+ return std::min(memory_layout_size, static_cast<u32>(8_MiB));
}();
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
if (!cpu_addr || size == 0) {
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 31118886f..1e0823836 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -233,6 +233,8 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4
const VideoCommon::ImageInfo& info) {
if (IsPixelFormatASTC(info.format) && info.size.depth == 1 && !runtime.HasNativeASTC()) {
return Settings::values.accelerate_astc.GetValue() &&
+ Settings::values.astc_recompression.GetValue() ==
+ Settings::AstcRecompression::Uncompressed &&
!Settings::values.async_astc.GetValue();
}
// Disable other accelerated uploads for now as they don't implement swizzled uploads
@@ -437,6 +439,19 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
return GL_R32UI;
}
+[[nodiscard]] GLenum SelectAstcFormat(PixelFormat format, bool is_srgb) {
+ switch (Settings::values.astc_recompression.GetValue()) {
+ case Settings::AstcRecompression::Bc1:
+ return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ break;
+ case Settings::AstcRecompression::Bc3:
+ return is_srgb ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+ default:
+ return is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
+ }
+}
+
} // Anonymous namespace
ImageBufferMap::~ImageBufferMap() {
@@ -739,9 +754,16 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_,
if (IsConverted(runtime->device, info.format, info.type)) {
flags |= ImageFlagBits::Converted;
flags |= ImageFlagBits::CostlyLoad;
- gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
+
+ const bool is_srgb = IsPixelFormatSRGB(info.format);
+ gl_internal_format = is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
gl_format = GL_RGBA;
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+ if (IsPixelFormatASTC(info.format)) {
+ gl_internal_format = SelectAstcFormat(info.format, is_srgb);
+ gl_format = GL_NONE;
+ }
} else {
const auto& tuple = MaxwellToGL::GetFormatTuple(info.format);
gl_internal_format = tuple.internal_format;
@@ -1130,7 +1152,12 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
views{runtime.null_image_views} {
const Device& device = runtime.device;
if (True(image.flags & ImageFlagBits::Converted)) {
- internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
+ const bool is_srgb = IsPixelFormatSRGB(info.format);
+ internal_format = is_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
+
+ if (IsPixelFormatASTC(info.format)) {
+ internal_format = SelectAstcFormat(info.format, is_srgb);
+ }
} else {
internal_format = MaxwellToGL::GetFormatTuple(format).internal_format;
}
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 8853cf0f7..b75d7220d 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
#include "video_core/surface.h"
@@ -237,14 +238,25 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with
PixelFormat pixel_format) {
ASSERT(static_cast<size_t>(pixel_format) < std::size(tex_format_tuples));
FormatTuple tuple = tex_format_tuples[static_cast<size_t>(pixel_format)];
- // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively
+ // Transcode on hardware that doesn't support ASTC natively
if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) {
const bool is_srgb = with_srgb && VideoCore::Surface::IsPixelFormatSRGB(pixel_format);
- if (is_srgb) {
- tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32;
- } else {
- tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
- tuple.usage |= Storage;
+
+ switch (Settings::values.astc_recompression.GetValue()) {
+ case Settings::AstcRecompression::Uncompressed:
+ if (is_srgb) {
+ tuple.format = VK_FORMAT_A8B8G8R8_SRGB_PACK32;
+ } else {
+ tuple.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
+ tuple.usage |= Storage;
+ }
+ break;
+ case Settings::AstcRecompression::Bc1:
+ tuple.format = is_srgb ? VK_FORMAT_BC1_RGBA_SRGB_BLOCK : VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
+ break;
+ case Settings::AstcRecompression::Bc3:
+ tuple.format = is_srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
+ break;
}
}
const bool attachable = (tuple.usage & Attachable) != 0;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 4d0481f2a..77d72697e 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1268,7 +1268,9 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
if (Settings::values.async_astc.GetValue()) {
flags |= VideoCommon::ImageFlagBits::AsynchronousDecode;
- } else if (Settings::values.accelerate_astc.GetValue() && info.size.depth == 1) {
+ } else if (Settings::values.astc_recompression.GetValue() ==
+ Settings::AstcRecompression::Uncompressed &&
+ Settings::values.accelerate_astc.GetValue() && info.size.depth == 1) {
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
}
flags |= VideoCommon::ImageFlagBits::Converted;
@@ -1283,7 +1285,9 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu
.usage = VK_IMAGE_USAGE_STORAGE_BIT,
};
current_image = *original_image;
- if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported()) {
+ if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() &&
+ Settings::values.astc_recompression.GetValue() ==
+ Settings::AstcRecompression::Uncompressed) {
const auto& device = runtime->device.GetLogical();
storage_image_views.reserve(info.resources.levels);
for (s32 level = 0; level < info.resources.levels; ++level) {
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index f1071aa23..1463f157b 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -18,6 +18,8 @@
#include "common/bit_util.h"
#include "common/common_types.h"
#include "common/div_ceil.h"
+#include "common/scratch_buffer.h"
+#include "common/settings.h"
#include "video_core/compatible_formats.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/memory_manager.h"
@@ -28,6 +30,7 @@
#include "video_core/texture_cache/samples_helper.h"
#include "video_core/texture_cache/util.h"
#include "video_core/textures/astc.h"
+#include "video_core/textures/bcn.h"
#include "video_core/textures/decoders.h"
namespace VideoCommon {
@@ -585,6 +588,21 @@ u32 CalculateConvertedSizeBytes(const ImageInfo& info) noexcept {
return info.size.width * BytesPerBlock(info.format);
}
static constexpr Extent2D TILE_SIZE{1, 1};
+ if (IsPixelFormatASTC(info.format) && Settings::values.astc_recompression.GetValue() !=
+ Settings::AstcRecompression::Uncompressed) {
+ const u32 bpp_div =
+ Settings::values.astc_recompression.GetValue() == Settings::AstcRecompression::Bc1 ? 2
+ : 1;
+ // NumBlocksPerLayer doesn't account for this correctly, so we have to do it manually.
+ u32 output_size = 0;
+ for (s32 i = 0; i < info.resources.levels; i++) {
+ const auto mip_size = AdjustMipSize(info.size, i);
+ const u32 plane_dim =
+ Common::AlignUp(mip_size.width, 4U) * Common::AlignUp(mip_size.height, 4U);
+ output_size += (plane_dim * info.size.depth * info.resources.layers) / bpp_div;
+ }
+ return output_size;
+ }
return NumBlocksPerLayer(info, TILE_SIZE) * info.resources.layers * CONVERTED_BYTES_PER_BLOCK;
}
@@ -885,6 +903,7 @@ BufferCopy UploadBufferCopy(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr,
void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8> output,
std::span<BufferImageCopy> copies) {
u32 output_offset = 0;
+ Common::ScratchBuffer<u8> decode_scratch;
const Extent2D tile_size = DefaultBlockSize(info.format);
for (BufferImageCopy& copy : copies) {
@@ -895,22 +914,58 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8
ASSERT(copy.image_extent == mip_size);
ASSERT(copy.buffer_row_length == Common::AlignUp(mip_size.width, tile_size.width));
ASSERT(copy.buffer_image_height == Common::AlignUp(mip_size.height, tile_size.height));
- if (IsPixelFormatASTC(info.format)) {
+
+ const auto input_offset = input.subspan(copy.buffer_offset);
+ copy.buffer_offset = output_offset;
+ copy.buffer_row_length = mip_size.width;
+ copy.buffer_image_height = mip_size.height;
+
+ const auto recompression_setting = Settings::values.astc_recompression.GetValue();
+ const bool astc = IsPixelFormatASTC(info.format);
+
+ if (astc && recompression_setting == Settings::AstcRecompression::Uncompressed) {
Tegra::Texture::ASTC::Decompress(
- input.subspan(copy.buffer_offset), copy.image_extent.width,
- copy.image_extent.height,
+ input_offset, copy.image_extent.width, copy.image_extent.height,
copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width,
tile_size.height, output.subspan(output_offset));
+
+ output_offset += copy.image_extent.width * copy.image_extent.height *
+ copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK;
+ } else if (astc) {
+ // BC1 uses 0.5 bytes per texel
+ // BC3 uses 1 byte per texel
+ const auto compress = recompression_setting == Settings::AstcRecompression::Bc1
+ ? Tegra::Texture::BCN::CompressBC1
+ : Tegra::Texture::BCN::CompressBC3;
+ const auto bpp_div = recompression_setting == Settings::AstcRecompression::Bc1 ? 2 : 1;
+
+ const u32 plane_dim = copy.image_extent.width * copy.image_extent.height;
+ const u32 level_size = plane_dim * copy.image_extent.depth *
+ copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK;
+ decode_scratch.resize_destructive(level_size);
+
+ Tegra::Texture::ASTC::Decompress(
+ input_offset, copy.image_extent.width, copy.image_extent.height,
+ copy.image_subresource.num_layers * copy.image_extent.depth, tile_size.width,
+ tile_size.height, decode_scratch);
+
+ compress(decode_scratch, copy.image_extent.width, copy.image_extent.height,
+ copy.image_subresource.num_layers * copy.image_extent.depth,
+ output.subspan(output_offset));
+
+ const u32 aligned_plane_dim = Common::AlignUp(copy.image_extent.width, 4) *
+ Common::AlignUp(copy.image_extent.height, 4);
+
+ copy.buffer_size =
+ (aligned_plane_dim * copy.image_extent.depth * copy.image_subresource.num_layers) /
+ bpp_div;
+ output_offset += static_cast<u32>(copy.buffer_size);
} else {
- DecompressBC4(input.subspan(copy.buffer_offset), copy.image_extent,
- output.subspan(output_offset));
- }
- copy.buffer_offset = output_offset;
- copy.buffer_row_length = mip_size.width;
- copy.buffer_image_height = mip_size.height;
+ DecompressBC4(input_offset, copy.image_extent, output.subspan(output_offset));
- output_offset += copy.image_extent.width * copy.image_extent.height *
- copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK;
+ output_offset += copy.image_extent.width * copy.image_extent.height *
+ copy.image_subresource.num_layers * CONVERTED_BYTES_PER_BLOCK;
+ }
}
}
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index a68bc0d77..fef0be31d 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -16,8 +16,8 @@
#include "common/alignment.h"
#include "common/common_types.h"
#include "common/polyfill_ranges.h"
-#include "common/thread_worker.h"
#include "video_core/textures/astc.h"
+#include "video_core/textures/workers.h"
class InputBitStream {
public:
@@ -1656,8 +1656,7 @@ void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height,
const u32 rows = Common::DivideUp(height, block_height);
const u32 cols = Common::DivideUp(width, block_width);
- static Common::ThreadWorker workers{std::max(std::thread::hardware_concurrency(), 2U) / 2,
- "ASTCDecompress"};
+ Common::ThreadWorker& workers{GetThreadWorkers()};
for (u32 z = 0; z < depth; ++z) {
const u32 depth_offset = z * height * width * 4;
diff --git a/src/video_core/textures/bcn.cpp b/src/video_core/textures/bcn.cpp
new file mode 100644
index 000000000..671212a49
--- /dev/null
+++ b/src/video_core/textures/bcn.cpp
@@ -0,0 +1,87 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stb_dxt.h>
+#include <string.h>
+
+#include "common/alignment.h"
+#include "video_core/textures/bcn.h"
+#include "video_core/textures/workers.h"
+
+namespace Tegra::Texture::BCN {
+
+using BCNCompressor = void(u8* block_output, const u8* block_input, bool any_alpha);
+
+template <u32 BytesPerBlock, bool ThresholdAlpha = false>
+void CompressBCN(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
+ std::span<uint8_t> output, BCNCompressor f) {
+ constexpr u8 alpha_threshold = 128;
+ constexpr u32 bytes_per_px = 4;
+ const u32 plane_dim = width * height;
+
+ Common::ThreadWorker& workers{GetThreadWorkers()};
+
+ for (u32 z = 0; z < depth; z++) {
+ for (u32 y = 0; y < height; y += 4) {
+ auto compress_row = [z, y, width, height, plane_dim, f, data, output]() {
+ for (u32 x = 0; x < width; x += 4) {
+ // Gather 4x4 block of RGBA texels
+ u8 input_colors[4][4][4];
+ bool any_alpha = false;
+
+ for (u32 j = 0; j < 4; j++) {
+ for (u32 i = 0; i < 4; i++) {
+ const size_t coord =
+ (z * plane_dim + (y + j) * width + (x + i)) * bytes_per_px;
+
+ if ((x + i < width) && (y + j < height)) {
+ if constexpr (ThresholdAlpha) {
+ if (data[coord + 3] >= alpha_threshold) {
+ input_colors[j][i][0] = data[coord + 0];
+ input_colors[j][i][1] = data[coord + 1];
+ input_colors[j][i][2] = data[coord + 2];
+ input_colors[j][i][3] = 255;
+ } else {
+ any_alpha = true;
+ memset(input_colors[j][i], 0, bytes_per_px);
+ }
+ } else {
+ memcpy(input_colors[j][i], &data[coord], bytes_per_px);
+ }
+ } else {
+ memset(input_colors[j][i], 0, bytes_per_px);
+ }
+ }
+ }
+
+ const u32 bytes_per_row = BytesPerBlock * Common::DivideUp(width, 4U);
+ const u32 bytes_per_plane = bytes_per_row * Common::DivideUp(height, 4U);
+ f(output.data() + z * bytes_per_plane + (y / 4) * bytes_per_row +
+ (x / 4) * BytesPerBlock,
+ reinterpret_cast<u8*>(input_colors), any_alpha);
+ }
+ };
+ workers.QueueWork(std::move(compress_row));
+ }
+ workers.WaitForRequests();
+ }
+}
+
+void CompressBC1(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
+ std::span<uint8_t> output) {
+ CompressBCN<8, true>(data, width, height, depth, output,
+ [](u8* block_output, const u8* block_input, bool any_alpha) {
+ stb_compress_bc1_block(block_output, block_input, any_alpha,
+ STB_DXT_NORMAL);
+ });
+}
+
+void CompressBC3(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
+ std::span<uint8_t> output) {
+ CompressBCN<16, false>(data, width, height, depth, output,
+ [](u8* block_output, const u8* block_input, bool any_alpha) {
+ stb_compress_bc3_block(block_output, block_input, STB_DXT_NORMAL);
+ });
+}
+
+} // namespace Tegra::Texture::BCN
diff --git a/src/video_core/textures/bcn.h b/src/video_core/textures/bcn.h
new file mode 100644
index 000000000..6464af885
--- /dev/null
+++ b/src/video_core/textures/bcn.h
@@ -0,0 +1,17 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <span>
+#include <stdint.h>
+
+namespace Tegra::Texture::BCN {
+
+void CompressBC1(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
+ std::span<uint8_t> output);
+
+void CompressBC3(std::span<const uint8_t> data, uint32_t width, uint32_t height, uint32_t depth,
+ std::span<uint8_t> output);
+
+} // namespace Tegra::Texture::BCN
diff --git a/src/video_core/textures/workers.cpp b/src/video_core/textures/workers.cpp
new file mode 100644
index 000000000..a71c305f4
--- /dev/null
+++ b/src/video_core/textures/workers.cpp
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "video_core/textures/workers.h"
+
+namespace Tegra::Texture {
+
+Common::ThreadWorker& GetThreadWorkers() {
+ static Common::ThreadWorker workers{std::max(std::thread::hardware_concurrency(), 2U) / 2,
+ "ImageTranscode"};
+
+ return workers;
+}
+
+} // namespace Tegra::Texture
diff --git a/src/video_core/textures/workers.h b/src/video_core/textures/workers.h
new file mode 100644
index 000000000..008dd05b3
--- /dev/null
+++ b/src/video_core/textures/workers.h
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/thread_worker.h"
+
+namespace Tegra::Texture {
+
+Common::ThreadWorker& GetThreadWorkers();
+
+}
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index f6e6f2736..b49f78bc9 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1001,6 +1001,11 @@ u64 Device::GetDeviceMemoryUsage() const {
}
void Device::CollectPhysicalMemoryInfo() {
+ // Account for resolution scaling in memory limits
+ const size_t normal_memory = 6_GiB;
+ const size_t scaler_memory = 1_GiB * Settings::values.resolution_info.ScaleUp(1);
+
+ // Calculate limits using memory budget
VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{};
budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
const auto mem_info =
@@ -1030,6 +1035,7 @@ void Device::CollectPhysicalMemoryInfo() {
if (!is_integrated) {
const u64 reserve_memory = std::min<u64>(device_access_memory / 8, 1_GiB);
device_access_memory -= reserve_memory;
+ device_access_memory = std::min<u64>(device_access_memory, normal_memory + scaler_memory);
return;
}
const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage);