summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/kernel.cpp41
-rw-r--r--src/core/hle/kernel/process.cpp24
-rw-r--r--src/video_core/engines/engine_interface.h3
-rw-r--r--src/video_core/engines/fermi_2d.h2
-rw-r--r--src/video_core/engines/kepler_memory.h2
-rw-r--r--src/video_core/engines/maxwell_dma.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp11
-rw-r--r--src/video_core/texture_cache/util.cpp21
-rw-r--r--src/video_core/texture_cache/util.h5
10 files changed, 55 insertions, 60 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8fd990577..f7d3f218a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -67,8 +67,13 @@ struct KernelCore::Impl {
is_phantom_mode_for_singlecore = false;
InitializePhysicalCores();
- InitializeSystemResourceLimit(kernel, system);
- InitializeMemoryLayout();
+
+ // Derive the initial memory layout from the emulated board
+ KMemoryLayout memory_layout;
+ DeriveInitialMemoryLayout(memory_layout);
+ InitializeMemoryLayout(memory_layout);
+ InitializeSystemResourceLimit(kernel, system, memory_layout);
+ InitializeSlabHeaps();
InitializeSchedulers();
InitializeSuspendThreads();
InitializePreemption(kernel);
@@ -137,27 +142,32 @@ struct KernelCore::Impl {
}
// Creates the default system resource limit
- void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
+ void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system,
+ const KMemoryLayout& memory_layout) {
system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
// If setting the default system values fails, then something seriously wrong has occurred.
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size)
.IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
.IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
+ system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size);
- // Derived from recent software updates. The kernel reserves 27MB
- constexpr u64 kernel_size{0x1b00000};
- if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) {
- UNREACHABLE();
- }
// Reserve secure applet memory, introduced in firmware 5.0.0
- constexpr u64 secure_applet_memory_size{0x400000};
+ constexpr u64 secure_applet_memory_size{Common::Size_4_MB};
ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
secure_applet_memory_size));
+
+ // This memory seems to be reserved on hardware, but is not reserved/used by yuzu.
+ // Likely Horizon OS reserved memory
+ // TODO(ameerj): Derive the memory rather than hardcode it.
+ constexpr u64 unknown_reserved_memory{0x2f896000};
+ ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
+ unknown_reserved_memory));
}
void InitializePreemption(KernelCore& kernel) {
@@ -531,11 +541,7 @@ struct KernelCore::Impl {
linear_region_start);
}
- void InitializeMemoryLayout() {
- // Derive the initial memory layout from the emulated board
- KMemoryLayout memory_layout;
- DeriveInitialMemoryLayout(memory_layout);
-
+ void InitializeMemoryLayout(const KMemoryLayout& memory_layout) {
const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
@@ -578,11 +584,14 @@ struct KernelCore::Impl {
system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize},
KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
"Time:SharedMemory");
+ }
+ void InitializeSlabHeaps() {
// Allocate slab heaps
user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
- constexpr u64 user_slab_heap_size{0x1ef000};
+ // TODO(ameerj): This should be derived, not hardcoded within the kernel
+ constexpr u64 user_slab_heap_size{0x3de000};
// Reserve slab heaps
ASSERT(
system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 9d5956ead..dd01f3924 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -120,9 +120,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
std::shared_ptr<Process> process = std::make_shared<Process>(system);
process->name = std::move(name);
- // TODO: This is inaccurate
- // The process should hold a reference to the kernel-wide resource limit.
- process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ process->resource_limit = kernel.GetSystemResourceLimit();
process->status = ProcessStatus::Created;
process->program_id = 0;
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -160,17 +158,13 @@ void Process::DecrementThreadCount() {
}
u64 Process::GetTotalPhysicalMemoryAvailable() const {
- // TODO: This is expected to always return the application memory pool size after accurately
- // reserving kernel resources. The current workaround uses a process-local resource limit of
- // application memory pool size, which is inaccurate.
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
main_thread_stack_size};
-
+ ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
if (capacity < memory_usage_capacity) {
return capacity;
}
-
return memory_usage_capacity;
}
@@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
system_resource_size = metadata.GetSystemResourceSize();
image_size = code_size;
- // Set initial resource limits
- resource_limit->SetLimitValue(
- LimitableResource::PhysicalMemory,
- kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
code_size + system_resource_size);
if (!memory_reservation.Succeeded()) {
@@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
UNREACHABLE();
}
- // Set initial resource limits
- resource_limit->SetLimitValue(
- LimitableResource::PhysicalMemory,
- kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
-
- resource_limit->SetLimitValue(LimitableResource::Threads, 608);
- resource_limit->SetLimitValue(LimitableResource::Events, 700);
- resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
- resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
-
// Create TLS region
tls_region_address = CreateTLSRegion();
memory_reservation.Commit();
diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h
index 18a9db7e6..c7ffd68c5 100644
--- a/src/video_core/engines/engine_interface.h
+++ b/src/video_core/engines/engine_interface.h
@@ -4,13 +4,14 @@
#pragma once
-#include <type_traits>
#include "common/common_types.h"
namespace Tegra::Engines {
class EngineInterface {
public:
+ virtual ~EngineInterface() = default;
+
/// Write the value to the register identified by method.
virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0;
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index c808a577d..a4170ffff 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -35,7 +35,7 @@ namespace Tegra::Engines {
class Fermi2D final : public EngineInterface {
public:
explicit Fermi2D();
- ~Fermi2D();
+ ~Fermi2D() override;
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index 19808a5c6..0d8ea09a9 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -36,7 +36,7 @@ namespace Tegra::Engines {
class KeplerMemory final : public EngineInterface {
public:
explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager);
- ~KeplerMemory();
+ ~KeplerMemory() override;
/// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 3c59eeb13..c77f02a22 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -188,7 +188,7 @@ public:
static_assert(sizeof(RemapConst) == 12);
explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_);
- ~MaxwellDMA();
+ ~MaxwellDMA() override;
/// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h
index 2c7ed654d..4b6d64daa 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.h
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h
@@ -35,8 +35,8 @@ public:
}
/// Returns true when a tick has been hit by the GPU.
- [[nodiscard]] bool IsFree(u64 tick) {
- return gpu_tick.load(std::memory_order_relaxed) >= tick;
+ [[nodiscard]] bool IsFree(u64 tick) const noexcept {
+ return KnownGpuTick() >= tick;
}
/// Advance to the logical tick.
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 18155e449..bc2a53841 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -7,6 +7,8 @@
#include <span>
#include <vector>
+#include "common/bit_cast.h"
+
#include "video_core/engines/fermi_2d.h"
#include "video_core/renderer_vulkan/blit_image.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
@@ -1062,14 +1064,13 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) {
Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
const auto& device = runtime.device;
const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported();
- const std::array<float, 4> color = tsc.BorderColor();
- // C++20 bit_cast
- VkClearColorValue border_color;
- std::memcpy(&border_color, &color, sizeof(color));
+ const auto color = tsc.BorderColor();
+
const VkSamplerCustomBorderColorCreateInfoEXT border_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
.pNext = nullptr,
- .customBorderColor = border_color,
+ // TODO: Make use of std::bit_cast once libc++ supports it.
+ .customBorderColor = Common::BitCast<VkClearColorValue>(color),
.format = VK_FORMAT_UNDEFINED,
};
const void* pnext = nullptr;
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index c22dd0148..0ab297413 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -268,16 +268,19 @@ template <u32 GOB_EXTENT>
return num_tiles << shift;
}
-[[nodiscard]] constexpr std::array<u32, MAX_MIP_LEVELS> CalculateLevelSizes(const LevelInfo& info,
- u32 num_levels) {
+[[nodiscard]] constexpr LevelArray CalculateLevelSizes(const LevelInfo& info, u32 num_levels) {
ASSERT(num_levels <= MAX_MIP_LEVELS);
- std::array<u32, MAX_MIP_LEVELS> sizes{};
+ LevelArray sizes{};
for (u32 level = 0; level < num_levels; ++level) {
sizes[level] = CalculateLevelSize(info, level);
}
return sizes;
}
+[[nodiscard]] u32 CalculateLevelBytes(const LevelArray& sizes, u32 num_levels) {
+ return std::reduce(sizes.begin(), sizes.begin() + num_levels, 0U);
+}
+
[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block,
u32 num_samples, u32 tile_width_spacing) {
const auto [samples_x, samples_y] = Samples(num_samples);
@@ -566,10 +569,10 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
const u32 num_levels = info.resources.levels;
const std::array sizes = CalculateLevelSizes(level_info, num_levels);
- size_t guest_offset = std::reduce(sizes.begin(), sizes.begin() + level, 0);
+ size_t guest_offset = CalculateLevelBytes(sizes, level);
const size_t layer_stride =
- AlignLayerSize(std::reduce(sizes.begin(), sizes.begin() + num_levels, 0), size,
- level_info.block, tile_size.height, info.tile_width_spacing);
+ AlignLayerSize(CalculateLevelBytes(sizes, num_levels), size, level_info.block,
+ tile_size.height, info.tile_width_spacing);
const size_t subresource_size = sizes[level];
const auto dst_data = std::make_unique<u8[]>(subresource_size);
@@ -643,10 +646,10 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept {
info.tile_width_spacing, info.resources.levels);
}
-std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
+LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS));
const LevelInfo level_info = MakeLevelInfo(info);
- std::array<u32, MAX_MIP_LEVELS> offsets{};
+ LevelArray offsets{};
u32 offset = 0;
for (s32 level = 0; level < info.resources.levels; ++level) {
offsets[level] = offset;
@@ -812,7 +815,7 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP
const Extent2D tile_size = DefaultBlockSize(info.format);
const std::array level_sizes = CalculateLevelSizes(level_info, num_levels);
const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing);
- const u32 layer_size = std::reduce(level_sizes.begin(), level_sizes.begin() + num_levels, 0);
+ const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels);
const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height,
info.tile_width_spacing);
size_t guest_offset = 0;
diff --git a/src/video_core/texture_cache/util.h b/src/video_core/texture_cache/util.h
index 4d0072867..cdc5cbc75 100644
--- a/src/video_core/texture_cache/util.h
+++ b/src/video_core/texture_cache/util.h
@@ -20,6 +20,8 @@ namespace VideoCommon {
using Tegra::Texture::TICEntry;
+using LevelArray = std::array<u32, MAX_MIP_LEVELS>;
+
struct OverlapResult {
GPUVAddr gpu_addr;
VAddr cpu_addr;
@@ -36,8 +38,7 @@ struct OverlapResult {
[[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept;
-[[nodiscard]] std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(
- const ImageInfo& info) noexcept;
+[[nodiscard]] LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept;
[[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info);