diff options
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 41 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 24 | ||||
| -rw-r--r-- | src/video_core/engines/engine_interface.h | 3 | ||||
| -rw-r--r-- | src/video_core/engines/fermi_2d.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/kepler_memory.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_dma.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_master_semaphore.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/texture_cache/util.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/texture_cache/util.h | 5 |
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 { | |||
| 67 | is_phantom_mode_for_singlecore = false; | 67 | is_phantom_mode_for_singlecore = false; |
| 68 | 68 | ||
| 69 | InitializePhysicalCores(); | 69 | InitializePhysicalCores(); |
| 70 | InitializeSystemResourceLimit(kernel, system); | 70 | |
| 71 | InitializeMemoryLayout(); | 71 | // Derive the initial memory layout from the emulated board |
| 72 | KMemoryLayout memory_layout; | ||
| 73 | DeriveInitialMemoryLayout(memory_layout); | ||
| 74 | InitializeMemoryLayout(memory_layout); | ||
| 75 | InitializeSystemResourceLimit(kernel, system, memory_layout); | ||
| 76 | InitializeSlabHeaps(); | ||
| 72 | InitializeSchedulers(); | 77 | InitializeSchedulers(); |
| 73 | InitializeSuspendThreads(); | 78 | InitializeSuspendThreads(); |
| 74 | InitializePreemption(kernel); | 79 | InitializePreemption(kernel); |
| @@ -137,27 +142,32 @@ struct KernelCore::Impl { | |||
| 137 | } | 142 | } |
| 138 | 143 | ||
| 139 | // Creates the default system resource limit | 144 | // Creates the default system resource limit |
| 140 | void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { | 145 | void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system, |
| 146 | const KMemoryLayout& memory_layout) { | ||
| 141 | system_resource_limit = std::make_shared<KResourceLimit>(kernel, system); | 147 | system_resource_limit = std::make_shared<KResourceLimit>(kernel, system); |
| 148 | const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); | ||
| 142 | 149 | ||
| 143 | // If setting the default system values fails, then something seriously wrong has occurred. | 150 | // If setting the default system values fails, then something seriously wrong has occurred. |
| 144 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) | 151 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) |
| 145 | .IsSuccess()); | 152 | .IsSuccess()); |
| 146 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); | 153 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); |
| 147 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); | 154 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); |
| 148 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) | 155 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) |
| 149 | .IsSuccess()); | 156 | .IsSuccess()); |
| 150 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); | 157 | ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); |
| 158 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); | ||
| 151 | 159 | ||
| 152 | // Derived from recent software updates. The kernel reserves 27MB | ||
| 153 | constexpr u64 kernel_size{0x1b00000}; | ||
| 154 | if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) { | ||
| 155 | UNREACHABLE(); | ||
| 156 | } | ||
| 157 | // Reserve secure applet memory, introduced in firmware 5.0.0 | 160 | // Reserve secure applet memory, introduced in firmware 5.0.0 |
| 158 | constexpr u64 secure_applet_memory_size{0x400000}; | 161 | constexpr u64 secure_applet_memory_size{Common::Size_4_MB}; |
| 159 | ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | 162 | ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, |
| 160 | secure_applet_memory_size)); | 163 | secure_applet_memory_size)); |
| 164 | |||
| 165 | // This memory seems to be reserved on hardware, but is not reserved/used by yuzu. | ||
| 166 | // Likely Horizon OS reserved memory | ||
| 167 | // TODO(ameerj): Derive the memory rather than hardcode it. | ||
| 168 | constexpr u64 unknown_reserved_memory{0x2f896000}; | ||
| 169 | ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | ||
| 170 | unknown_reserved_memory)); | ||
| 161 | } | 171 | } |
| 162 | 172 | ||
| 163 | void InitializePreemption(KernelCore& kernel) { | 173 | void InitializePreemption(KernelCore& kernel) { |
| @@ -531,11 +541,7 @@ struct KernelCore::Impl { | |||
| 531 | linear_region_start); | 541 | linear_region_start); |
| 532 | } | 542 | } |
| 533 | 543 | ||
| 534 | void InitializeMemoryLayout() { | 544 | void InitializeMemoryLayout(const KMemoryLayout& memory_layout) { |
| 535 | // Derive the initial memory layout from the emulated board | ||
| 536 | KMemoryLayout memory_layout; | ||
| 537 | DeriveInitialMemoryLayout(memory_layout); | ||
| 538 | |||
| 539 | const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents(); | 545 | const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents(); |
| 540 | const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents(); | 546 | const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents(); |
| 541 | const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); | 547 | const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); |
| @@ -578,11 +584,14 @@ struct KernelCore::Impl { | |||
| 578 | system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize}, | 584 | system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize}, |
| 579 | KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size, | 585 | KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size, |
| 580 | "Time:SharedMemory"); | 586 | "Time:SharedMemory"); |
| 587 | } | ||
| 581 | 588 | ||
| 589 | void InitializeSlabHeaps() { | ||
| 582 | // Allocate slab heaps | 590 | // Allocate slab heaps |
| 583 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); | 591 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); |
| 584 | 592 | ||
| 585 | constexpr u64 user_slab_heap_size{0x1ef000}; | 593 | // TODO(ameerj): This should be derived, not hardcoded within the kernel |
| 594 | constexpr u64 user_slab_heap_size{0x3de000}; | ||
| 586 | // Reserve slab heaps | 595 | // Reserve slab heaps |
| 587 | ASSERT( | 596 | ASSERT( |
| 588 | system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); | 597 | 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, | |||
| 120 | std::shared_ptr<Process> process = std::make_shared<Process>(system); | 120 | std::shared_ptr<Process> process = std::make_shared<Process>(system); |
| 121 | process->name = std::move(name); | 121 | process->name = std::move(name); |
| 122 | 122 | ||
| 123 | // TODO: This is inaccurate | 123 | process->resource_limit = kernel.GetSystemResourceLimit(); |
| 124 | // The process should hold a reference to the kernel-wide resource limit. | ||
| 125 | process->resource_limit = std::make_shared<KResourceLimit>(kernel, system); | ||
| 126 | process->status = ProcessStatus::Created; | 124 | process->status = ProcessStatus::Created; |
| 127 | process->program_id = 0; | 125 | process->program_id = 0; |
| 128 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() | 126 | process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() |
| @@ -160,17 +158,13 @@ void Process::DecrementThreadCount() { | |||
| 160 | } | 158 | } |
| 161 | 159 | ||
| 162 | u64 Process::GetTotalPhysicalMemoryAvailable() const { | 160 | u64 Process::GetTotalPhysicalMemoryAvailable() const { |
| 163 | // TODO: This is expected to always return the application memory pool size after accurately | ||
| 164 | // reserving kernel resources. The current workaround uses a process-local resource limit of | ||
| 165 | // application memory pool size, which is inaccurate. | ||
| 166 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | 161 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + |
| 167 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | 162 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + |
| 168 | main_thread_stack_size}; | 163 | main_thread_stack_size}; |
| 169 | 164 | ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | |
| 170 | if (capacity < memory_usage_capacity) { | 165 | if (capacity < memory_usage_capacity) { |
| 171 | return capacity; | 166 | return capacity; |
| 172 | } | 167 | } |
| 173 | |||
| 174 | return memory_usage_capacity; | 168 | return memory_usage_capacity; |
| 175 | } | 169 | } |
| 176 | 170 | ||
| @@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 272 | system_resource_size = metadata.GetSystemResourceSize(); | 266 | system_resource_size = metadata.GetSystemResourceSize(); |
| 273 | image_size = code_size; | 267 | image_size = code_size; |
| 274 | 268 | ||
| 275 | // Set initial resource limits | ||
| 276 | resource_limit->SetLimitValue( | ||
| 277 | LimitableResource::PhysicalMemory, | ||
| 278 | kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||
| 279 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | 269 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, |
| 280 | code_size + system_resource_size); | 270 | code_size + system_resource_size); |
| 281 | if (!memory_reservation.Succeeded()) { | 271 | if (!memory_reservation.Succeeded()) { |
| @@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 324 | UNREACHABLE(); | 314 | UNREACHABLE(); |
| 325 | } | 315 | } |
| 326 | 316 | ||
| 327 | // Set initial resource limits | ||
| 328 | resource_limit->SetLimitValue( | ||
| 329 | LimitableResource::PhysicalMemory, | ||
| 330 | kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||
| 331 | |||
| 332 | resource_limit->SetLimitValue(LimitableResource::Threads, 608); | ||
| 333 | resource_limit->SetLimitValue(LimitableResource::Events, 700); | ||
| 334 | resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); | ||
| 335 | resource_limit->SetLimitValue(LimitableResource::Sessions, 894); | ||
| 336 | |||
| 337 | // Create TLS region | 317 | // Create TLS region |
| 338 | tls_region_address = CreateTLSRegion(); | 318 | tls_region_address = CreateTLSRegion(); |
| 339 | memory_reservation.Commit(); | 319 | 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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <type_traits> | ||
| 8 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 9 | 8 | ||
| 10 | namespace Tegra::Engines { | 9 | namespace Tegra::Engines { |
| 11 | 10 | ||
| 12 | class EngineInterface { | 11 | class EngineInterface { |
| 13 | public: | 12 | public: |
| 13 | virtual ~EngineInterface() = default; | ||
| 14 | |||
| 14 | /// Write the value to the register identified by method. | 15 | /// Write the value to the register identified by method. |
| 15 | virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; | 16 | virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; |
| 16 | 17 | ||
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 { | |||
| 35 | class Fermi2D final : public EngineInterface { | 35 | class Fermi2D final : public EngineInterface { |
| 36 | public: | 36 | public: |
| 37 | explicit Fermi2D(); | 37 | explicit Fermi2D(); |
| 38 | ~Fermi2D(); | 38 | ~Fermi2D() override; |
| 39 | 39 | ||
| 40 | /// Binds a rasterizer to this engine. | 40 | /// Binds a rasterizer to this engine. |
| 41 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | 41 | 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 { | |||
| 36 | class KeplerMemory final : public EngineInterface { | 36 | class KeplerMemory final : public EngineInterface { |
| 37 | public: | 37 | public: |
| 38 | explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); | 38 | explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); |
| 39 | ~KeplerMemory(); | 39 | ~KeplerMemory() override; |
| 40 | 40 | ||
| 41 | /// Write the value to the register identified by method. | 41 | /// Write the value to the register identified by method. |
| 42 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 42 | 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: | |||
| 188 | static_assert(sizeof(RemapConst) == 12); | 188 | static_assert(sizeof(RemapConst) == 12); |
| 189 | 189 | ||
| 190 | explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); | 190 | explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); |
| 191 | ~MaxwellDMA(); | 191 | ~MaxwellDMA() override; |
| 192 | 192 | ||
| 193 | /// Write the value to the register identified by method. | 193 | /// Write the value to the register identified by method. |
| 194 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 194 | 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: | |||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /// Returns true when a tick has been hit by the GPU. | 37 | /// Returns true when a tick has been hit by the GPU. |
| 38 | [[nodiscard]] bool IsFree(u64 tick) { | 38 | [[nodiscard]] bool IsFree(u64 tick) const noexcept { |
| 39 | return gpu_tick.load(std::memory_order_relaxed) >= tick; | 39 | return KnownGpuTick() >= tick; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | /// Advance to the logical tick. | 42 | /// 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 @@ | |||
| 7 | #include <span> | 7 | #include <span> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/bit_cast.h" | ||
| 11 | |||
| 10 | #include "video_core/engines/fermi_2d.h" | 12 | #include "video_core/engines/fermi_2d.h" |
| 11 | #include "video_core/renderer_vulkan/blit_image.h" | 13 | #include "video_core/renderer_vulkan/blit_image.h" |
| 12 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 14 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| @@ -1062,14 +1064,13 @@ vk::ImageView ImageView::MakeDepthStencilView(VkImageAspectFlags aspect_mask) { | |||
| 1062 | Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { | 1064 | Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) { |
| 1063 | const auto& device = runtime.device; | 1065 | const auto& device = runtime.device; |
| 1064 | const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); | 1066 | const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); |
| 1065 | const std::array<float, 4> color = tsc.BorderColor(); | 1067 | const auto color = tsc.BorderColor(); |
| 1066 | // C++20 bit_cast | 1068 | |
| 1067 | VkClearColorValue border_color; | ||
| 1068 | std::memcpy(&border_color, &color, sizeof(color)); | ||
| 1069 | const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ | 1069 | const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ |
| 1070 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, | 1070 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, |
| 1071 | .pNext = nullptr, | 1071 | .pNext = nullptr, |
| 1072 | .customBorderColor = border_color, | 1072 | // TODO: Make use of std::bit_cast once libc++ supports it. |
| 1073 | .customBorderColor = Common::BitCast<VkClearColorValue>(color), | ||
| 1073 | .format = VK_FORMAT_UNDEFINED, | 1074 | .format = VK_FORMAT_UNDEFINED, |
| 1074 | }; | 1075 | }; |
| 1075 | const void* pnext = nullptr; | 1076 | 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> | |||
| 268 | return num_tiles << shift; | 268 | return num_tiles << shift; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | [[nodiscard]] constexpr std::array<u32, MAX_MIP_LEVELS> CalculateLevelSizes(const LevelInfo& info, | 271 | [[nodiscard]] constexpr LevelArray CalculateLevelSizes(const LevelInfo& info, u32 num_levels) { |
| 272 | u32 num_levels) { | ||
| 273 | ASSERT(num_levels <= MAX_MIP_LEVELS); | 272 | ASSERT(num_levels <= MAX_MIP_LEVELS); |
| 274 | std::array<u32, MAX_MIP_LEVELS> sizes{}; | 273 | LevelArray sizes{}; |
| 275 | for (u32 level = 0; level < num_levels; ++level) { | 274 | for (u32 level = 0; level < num_levels; ++level) { |
| 276 | sizes[level] = CalculateLevelSize(info, level); | 275 | sizes[level] = CalculateLevelSize(info, level); |
| 277 | } | 276 | } |
| 278 | return sizes; | 277 | return sizes; |
| 279 | } | 278 | } |
| 280 | 279 | ||
| 280 | [[nodiscard]] u32 CalculateLevelBytes(const LevelArray& sizes, u32 num_levels) { | ||
| 281 | return std::reduce(sizes.begin(), sizes.begin() + num_levels, 0U); | ||
| 282 | } | ||
| 283 | |||
| 281 | [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, | 284 | [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, |
| 282 | u32 num_samples, u32 tile_width_spacing) { | 285 | u32 num_samples, u32 tile_width_spacing) { |
| 283 | const auto [samples_x, samples_y] = Samples(num_samples); | 286 | const auto [samples_x, samples_y] = Samples(num_samples); |
| @@ -566,10 +569,10 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr | |||
| 566 | 569 | ||
| 567 | const u32 num_levels = info.resources.levels; | 570 | const u32 num_levels = info.resources.levels; |
| 568 | const std::array sizes = CalculateLevelSizes(level_info, num_levels); | 571 | const std::array sizes = CalculateLevelSizes(level_info, num_levels); |
| 569 | size_t guest_offset = std::reduce(sizes.begin(), sizes.begin() + level, 0); | 572 | size_t guest_offset = CalculateLevelBytes(sizes, level); |
| 570 | const size_t layer_stride = | 573 | const size_t layer_stride = |
| 571 | AlignLayerSize(std::reduce(sizes.begin(), sizes.begin() + num_levels, 0), size, | 574 | AlignLayerSize(CalculateLevelBytes(sizes, num_levels), size, level_info.block, |
| 572 | level_info.block, tile_size.height, info.tile_width_spacing); | 575 | tile_size.height, info.tile_width_spacing); |
| 573 | const size_t subresource_size = sizes[level]; | 576 | const size_t subresource_size = sizes[level]; |
| 574 | 577 | ||
| 575 | const auto dst_data = std::make_unique<u8[]>(subresource_size); | 578 | const auto dst_data = std::make_unique<u8[]>(subresource_size); |
| @@ -643,10 +646,10 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept { | |||
| 643 | info.tile_width_spacing, info.resources.levels); | 646 | info.tile_width_spacing, info.resources.levels); |
| 644 | } | 647 | } |
| 645 | 648 | ||
| 646 | std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { | 649 | LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept { |
| 647 | ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); | 650 | ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); |
| 648 | const LevelInfo level_info = MakeLevelInfo(info); | 651 | const LevelInfo level_info = MakeLevelInfo(info); |
| 649 | std::array<u32, MAX_MIP_LEVELS> offsets{}; | 652 | LevelArray offsets{}; |
| 650 | u32 offset = 0; | 653 | u32 offset = 0; |
| 651 | for (s32 level = 0; level < info.resources.levels; ++level) { | 654 | for (s32 level = 0; level < info.resources.levels; ++level) { |
| 652 | offsets[level] = offset; | 655 | offsets[level] = offset; |
| @@ -812,7 +815,7 @@ std::vector<BufferImageCopy> UnswizzleImage(Tegra::MemoryManager& gpu_memory, GP | |||
| 812 | const Extent2D tile_size = DefaultBlockSize(info.format); | 815 | const Extent2D tile_size = DefaultBlockSize(info.format); |
| 813 | const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); | 816 | const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); |
| 814 | const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); | 817 | const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); |
| 815 | const u32 layer_size = std::reduce(level_sizes.begin(), level_sizes.begin() + num_levels, 0); | 818 | const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels); |
| 816 | const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, | 819 | const u32 layer_stride = AlignLayerSize(layer_size, size, level_info.block, tile_size.height, |
| 817 | info.tile_width_spacing); | 820 | info.tile_width_spacing); |
| 818 | size_t guest_offset = 0; | 821 | 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 { | |||
| 20 | 20 | ||
| 21 | using Tegra::Texture::TICEntry; | 21 | using Tegra::Texture::TICEntry; |
| 22 | 22 | ||
| 23 | using LevelArray = std::array<u32, MAX_MIP_LEVELS>; | ||
| 24 | |||
| 23 | struct OverlapResult { | 25 | struct OverlapResult { |
| 24 | GPUVAddr gpu_addr; | 26 | GPUVAddr gpu_addr; |
| 25 | VAddr cpu_addr; | 27 | VAddr cpu_addr; |
| @@ -36,8 +38,7 @@ struct OverlapResult { | |||
| 36 | 38 | ||
| 37 | [[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; | 39 | [[nodiscard]] u32 CalculateLayerSize(const ImageInfo& info) noexcept; |
| 38 | 40 | ||
| 39 | [[nodiscard]] std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets( | 41 | [[nodiscard]] LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept; |
| 40 | const ImageInfo& info) noexcept; | ||
| 41 | 42 | ||
| 42 | [[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); | 43 | [[nodiscard]] std::vector<u32> CalculateSliceOffsets(const ImageInfo& info); |
| 43 | 44 | ||