aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2025-07-13 03:40:48 +0200
committercrueter <crueter@eden-emu.dev>2025-07-13 03:40:48 +0200
commit5091759a47182fd85e12ca58abcb57d6f4ca1ea1 (patch)
treebc9aa9de346c4a24b6b7aafca73462e5905d2ad4 /src
parent03351a4f8b463a798d64dcb78899b4cdd9004071 (diff)
[vk, opengl] defer checks to topmost call (avoid unnecessary call) (#40)
Co-authored-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/40 Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/core/memory.cpp69
-rw-r--r--src/video_core/gpu.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp46
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp7
4 files changed, 66 insertions, 61 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index b033858bf8..34539cc650 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -868,35 +871,35 @@ struct Memory::Impl {
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, auto on_unmapped, auto on_rasterizer) const {
// AARCH64 masks the upper 16 bit of all memory accesses
vaddr = vaddr & 0xffffffffffffULL;
-
if (!AddressSpaceContains(*current_page_table, vaddr, 1)) [[unlikely]] {
on_unmapped();
return nullptr;
+ } else {
+ // Avoid adding any extra logic to this fast-path block
+ const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
+ if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
+ return reinterpret_cast<u8*>(pointer + vaddr);
+ } else {
+ switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
+ case Common::PageType::Unmapped:
+ on_unmapped();
+ return nullptr;
+ case Common::PageType::Memory:
+ ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
+ return nullptr;
+ case Common::PageType::DebugMemory:
+ return GetPointerFromDebugMemory(vaddr);
+ case Common::PageType::RasterizerCachedMemory: {
+ u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
+ on_rasterizer();
+ return host_ptr;
+ }
+ default:
+ UNREACHABLE();
+ }
+ return nullptr;
+ }
}
-
- // Avoid adding any extra logic to this fast-path block
- const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
- if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
- return reinterpret_cast<u8*>(pointer + vaddr);
- }
- switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
- case Common::PageType::Unmapped:
- on_unmapped();
- return nullptr;
- case Common::PageType::Memory:
- ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
- return nullptr;
- case Common::PageType::DebugMemory:
- return GetPointerFromDebugMemory(vaddr);
- case Common::PageType::RasterizerCachedMemory: {
- u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
- on_rasterizer();
- return host_ptr;
- }
- default:
- UNREACHABLE();
- }
- return nullptr;
}
[[nodiscard]] u8* GetPointer(const Common::ProcessAddress vaddr) const {
@@ -1149,13 +1152,19 @@ struct Memory::Impl {
gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) {
auto& current_area = rasterizer_write_areas[core];
PAddr subaddress = address >> YUZU_PAGEBITS;
- bool do_collection = current_area.last_address == subaddress;
- if (!do_collection) [[unlikely]] {
- do_collection = system.GPU().OnCPUWrite(address, size);
- if (!do_collection) {
+ // Performance note:
+ // It may not be a good idea to assume accesses are within the same subaddress (i.e same page)
+ // It is often the case the games like to access wildly different addresses. Hence why I propose
+ // we should let the compiler just do it's thing...
+ if (current_area.last_address != subaddress) {
+ // Short circuit the need to check for address/size
+ auto const do_collection = (address != 0 && size != 0)
+ && system.GPU().OnCPUWrite(address, size);
+ if (do_collection) {
+ current_area.last_address = subaddress;
+ } else {
return;
}
- current_area.last_address = subaddress;
}
gpu_dirty_managers[core].Collect(address, size);
});
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 8a06adad79..538c4da85a 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -244,7 +247,7 @@ public:
void InvalidateRegion(DAddr addr, u64 size);
/// Notify rasterizer that CPU is trying to write this area. It returns true if the area is
- /// sensible, false otherwise
+ /// sensible, false otherwise, addr and size must be a valid combination
bool OnCPUWrite(DAddr addr, u64 size);
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 19f586518f..4fb193293b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -565,22 +568,17 @@ void RasterizerOpenGL::InvalidateRegion(DAddr addr, u64 size, VideoCommon::Cache
bool RasterizerOpenGL::OnCPUWrite(DAddr addr, u64 size) {
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
- if (addr == 0 || size == 0) {
- return false;
- }
-
+ DEBUG_ASSERT(addr != 0 || size != 0);
{
std::scoped_lock lock{buffer_cache.mutex};
if (buffer_cache.OnCPUWrite(addr, size)) {
return true;
}
}
-
{
std::scoped_lock lock{texture_cache.mutex};
texture_cache.WriteMemory(addr, size);
}
-
shader_cache.InvalidateRegion(addr, size);
return false;
}
@@ -1204,24 +1202,24 @@ void RasterizerOpenGL::SyncLogicOpState() {
}
flags[Dirty::LogicOp] = false;
- auto& regs = maxwell3d->regs;
-
- if (device.IsAmd()) {
- using namespace Tegra::Engines;
- struct In {
- const Maxwell3D::Regs::VertexAttribute::Type d;
- In(Maxwell3D::Regs::VertexAttribute::Type n) : d(n) {}
- bool operator()(Maxwell3D::Regs::VertexAttribute n) const {
- return n.type == d;
- }
- };
-
- bool has_float =
- std::any_of(regs.vertex_attrib_format.begin(), regs.vertex_attrib_format.end(),
- In(Maxwell3D::Regs::VertexAttribute::Type::Float));
- regs.logic_op.enable = static_cast<u32>(!has_float);
- }
-
+ auto& regs = maxwell3d->regs;
+
+ if (device.IsAmd()) {
+ using namespace Tegra::Engines;
+ struct In {
+ const Maxwell3D::Regs::VertexAttribute::Type d;
+ In(Maxwell3D::Regs::VertexAttribute::Type n) : d(n) {}
+ bool operator()(Maxwell3D::Regs::VertexAttribute n) const {
+ return n.type == d;
+ }
+ };
+
+ bool has_float =
+ std::any_of(regs.vertex_attrib_format.begin(), regs.vertex_attrib_format.end(),
+ In(Maxwell3D::Regs::VertexAttribute::Type::Float));
+ regs.logic_op.enable = static_cast<u32>(!has_float);
+ }
+
if (regs.logic_op.enable) {
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(MaxwellToGL::LogicOp(regs.logic_op.op));
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 66f4668026..a2492f1d74 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -636,22 +636,17 @@ void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<DAddr, std::s
}
bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) {
- if (addr == 0 || size == 0) {
- return false;
- }
-
+ DEBUG_ASSERT(addr != 0 || size != 0);
{
std::scoped_lock lock{buffer_cache.mutex};
if (buffer_cache.OnCPUWrite(addr, size)) {
return true;
}
}
-
{
std::scoped_lock lock{texture_cache.mutex};
texture_cache.WriteMemory(addr, size);
}
-
pipeline_cache.InvalidateRegion(addr, size);
return false;
}