aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xREADME.md2
-rwxr-xr-xsrc/common/CMakeLists.txt1
-rwxr-xr-xsrc/common/range_mutex.h93
-rwxr-xr-xsrc/common/settings.h11
-rwxr-xr-xsrc/core/device_memory_manager.h3
-rwxr-xr-xsrc/core/device_memory_manager.inc16
-rwxr-xr-xsrc/core/file_sys/system_archive/system_archive.cpp12
-rwxr-xr-xsrc/core/hle/service/glue/time/manager.cpp3
-rwxr-xr-xsrc/core/hle/service/glue/time/time_zone_binary.cpp11
-rwxr-xr-xsrc/core/memory.cpp14
-rwxr-xr-xsrc/video_core/buffer_cache/buffer_cache.h5
-rwxr-xr-xsrc/video_core/renderer_opengl/renderer_opengl.cpp10
-rwxr-xr-xsrc/video_core/renderer_vulkan/vk_blit_screen.cpp8
-rwxr-xr-xsrc/video_core/renderer_vulkan/vk_query_cache.cpp14
14 files changed, 167 insertions, 36 deletions
diff --git a/README.md b/README.md
index 4d1bf4cd3..291256d6f 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
1yuzu emulator early access 1yuzu emulator early access
2============= 2=============
3 3
4This is the source code for early-access 4083. 4This is the source code for early-access 4084.
5 5
6## Legal Notice 6## Legal Notice
7 7
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index f1483331f..b008fbe6b 100755
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -106,6 +106,7 @@ add_library(common STATIC
106 precompiled_headers.h 106 precompiled_headers.h
107 quaternion.h 107 quaternion.h
108 range_map.h 108 range_map.h
109 range_mutex.h
109 reader_writer_queue.h 110 reader_writer_queue.h
110 ring_buffer.h 111 ring_buffer.h
111 ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp 112 ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
diff --git a/src/common/range_mutex.h b/src/common/range_mutex.h
new file mode 100755
index 000000000..d6c949811
--- /dev/null
+++ b/src/common/range_mutex.h
@@ -0,0 +1,93 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <condition_variable>
7#include <mutex>
8
9#include "common/intrusive_list.h"
10
11namespace Common {
12
13class ScopedRangeLock;
14
15class RangeMutex {
16public:
17 explicit RangeMutex() = default;
18 ~RangeMutex() = default;
19
20private:
21 friend class ScopedRangeLock;
22
23 void Lock(ScopedRangeLock& l);
24 void Unlock(ScopedRangeLock& l);
25 bool HasIntersectionLocked(ScopedRangeLock& l);
26
27private:
28 std::mutex m_mutex;
29 std::condition_variable m_cv;
30
31 using LockList = Common::IntrusiveListBaseTraits<ScopedRangeLock>::ListType;
32 LockList m_list;
33};
34
35class ScopedRangeLock : public Common::IntrusiveListBaseNode<ScopedRangeLock> {
36public:
37 explicit ScopedRangeLock(RangeMutex& mutex, u64 address, u64 size)
38 : m_mutex(mutex), m_address(address), m_size(size) {
39 if (m_size > 0) {
40 m_mutex.Lock(*this);
41 }
42 }
43 ~ScopedRangeLock() {
44 if (m_size > 0) {
45 m_mutex.Unlock(*this);
46 }
47 }
48
49 u64 GetAddress() const {
50 return m_address;
51 }
52
53 u64 GetSize() const {
54 return m_size;
55 }
56
57private:
58 RangeMutex& m_mutex;
59 const u64 m_address{};
60 const u64 m_size{};
61};
62
63inline void RangeMutex::Lock(ScopedRangeLock& l) {
64 std::unique_lock lk{m_mutex};
65 m_cv.wait(lk, [&] { return !HasIntersectionLocked(l); });
66 m_list.push_back(l);
67}
68
69inline void RangeMutex::Unlock(ScopedRangeLock& l) {
70 {
71 std::scoped_lock lk{m_mutex};
72 m_list.erase(m_list.iterator_to(l));
73 }
74 m_cv.notify_all();
75}
76
77inline bool RangeMutex::HasIntersectionLocked(ScopedRangeLock& l) {
78 const auto cur_begin = l.GetAddress();
79 const auto cur_last = l.GetAddress() + l.GetSize() - 1;
80
81 for (const auto& other : m_list) {
82 const auto other_begin = other.GetAddress();
83 const auto other_last = other.GetAddress() + other.GetSize() - 1;
84
85 if (cur_begin <= other_last && other_begin <= cur_last) {
86 return true;
87 }
88 }
89
90 return false;
91}
92
93} // namespace Common
diff --git a/src/common/settings.h b/src/common/settings.h
index db8606f93..a3e34528b 100755
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -420,8 +420,15 @@ struct Values {
420 SwitchableSetting<s64> custom_rtc{ 420 SwitchableSetting<s64> custom_rtc{
421 linkage, 0, "custom_rtc", Category::System, Specialization::Time, 421 linkage, 0, "custom_rtc", Category::System, Specialization::Time,
422 false, true, &custom_rtc_enabled}; 422 false, true, &custom_rtc_enabled};
423 SwitchableSetting<s64, false> custom_rtc_offset{ 423 SwitchableSetting<s64, true> custom_rtc_offset{linkage,
424 linkage, 0, "custom_rtc_offset", Category::System, Specialization::Countable, true, true}; 424 0,
425 std::numeric_limits<int>::min(),
426 std::numeric_limits<int>::max(),
427 "custom_rtc_offset",
428 Category::System,
429 Specialization::Countable,
430 true,
431 true};
425 SwitchableSetting<bool> rng_seed_enabled{ 432 SwitchableSetting<bool> rng_seed_enabled{
426 linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true}; 433 linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
427 SwitchableSetting<u32> rng_seed{ 434 SwitchableSetting<u32> rng_seed{
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h
index ffeed46cc..63823602c 100755
--- a/src/core/device_memory_manager.h
+++ b/src/core/device_memory_manager.h
@@ -10,6 +10,7 @@
10#include <mutex> 10#include <mutex>
11 11
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/range_mutex.h"
13#include "common/scratch_buffer.h" 14#include "common/scratch_buffer.h"
14#include "common/virtual_buffer.h" 15#include "common/virtual_buffer.h"
15 16
@@ -204,7 +205,7 @@ private:
204 (1ULL << (device_virtual_bits - page_bits)) / subentries; 205 (1ULL << (device_virtual_bits - page_bits)) / subentries;
205 using CachedPages = std::array<CounterEntry, num_counter_entries>; 206 using CachedPages = std::array<CounterEntry, num_counter_entries>;
206 std::unique_ptr<CachedPages> cached_pages; 207 std::unique_ptr<CachedPages> cached_pages;
207 std::mutex counter_guard; 208 Common::RangeMutex counter_guard;
208 std::mutex mapping_guard; 209 std::mutex mapping_guard;
209}; 210};
210 211
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
index 8ce122872..0a59000aa 100755
--- a/src/core/device_memory_manager.inc
+++ b/src/core/device_memory_manager.inc
@@ -31,9 +31,8 @@ public:
31 buffer.resize(0); 31 buffer.resize(0);
32 size_t index = 0; 32 size_t index = 0;
33 const auto add_value = [&](u32 value) { 33 const auto add_value = [&](u32 value) {
34 buffer[index] = value; 34 buffer.resize(index + 1);
35 index++; 35 buffer[index++] = value;
36 buffer.resize(index);
37 }; 36 };
38 37
39 u32 iter_entry = start_entry; 38 u32 iter_entry = start_entry;
@@ -509,12 +508,7 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
509 508
510template <typename Traits> 509template <typename Traits>
511void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { 510void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
512 std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock); 511 Common::ScopedRangeLock lk(counter_guard, addr, size);
513 const auto Lock = [&] {
514 if (!lk) {
515 lk.lock();
516 }
517 };
518 u64 uncache_begin = 0; 512 u64 uncache_begin = 0;
519 u64 cache_begin = 0; 513 u64 cache_begin = 0;
520 u64 uncache_bytes = 0; 514 u64 uncache_bytes = 0;
@@ -549,7 +543,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
549 } 543 }
550 uncache_bytes += Memory::YUZU_PAGESIZE; 544 uncache_bytes += Memory::YUZU_PAGESIZE;
551 } else if (uncache_bytes > 0) { 545 } else if (uncache_bytes > 0) {
552 Lock();
553 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, 546 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
554 uncache_bytes, false); 547 uncache_bytes, false);
555 uncache_bytes = 0; 548 uncache_bytes = 0;
@@ -560,7 +553,6 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
560 } 553 }
561 cache_bytes += Memory::YUZU_PAGESIZE; 554 cache_bytes += Memory::YUZU_PAGESIZE;
562 } else if (cache_bytes > 0) { 555 } else if (cache_bytes > 0) {
563 Lock();
564 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, 556 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
565 true); 557 true);
566 cache_bytes = 0; 558 cache_bytes = 0;
@@ -568,12 +560,10 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
568 vpage++; 560 vpage++;
569 } 561 }
570 if (uncache_bytes > 0) { 562 if (uncache_bytes > 0) {
571 Lock();
572 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, 563 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
573 false); 564 false);
574 } 565 }
575 if (cache_bytes > 0) { 566 if (cache_bytes > 0) {
576 Lock();
577 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, 567 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
578 true); 568 true);
579 } 569 }
diff --git a/src/core/file_sys/system_archive/system_archive.cpp b/src/core/file_sys/system_archive/system_archive.cpp
index 09caaface..2d62a92a5 100755
--- a/src/core/file_sys/system_archive/system_archive.cpp
+++ b/src/core/file_sys/system_archive/system_archive.cpp
@@ -67,25 +67,29 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
67}}; 67}};
68 68
69VirtualFile SynthesizeSystemArchive(const u64 title_id) { 69VirtualFile SynthesizeSystemArchive(const u64 title_id) {
70 if (title_id < SYSTEM_ARCHIVES.front().title_id || title_id > SYSTEM_ARCHIVES.back().title_id) 70 if (title_id < SYSTEM_ARCHIVES.front().title_id || title_id > SYSTEM_ARCHIVES.back().title_id) {
71 return nullptr; 71 return nullptr;
72 }
72 73
73 const auto& desc = SYSTEM_ARCHIVES[title_id - SYSTEM_ARCHIVE_BASE_TITLE_ID]; 74 const auto& desc = SYSTEM_ARCHIVES[title_id - SYSTEM_ARCHIVE_BASE_TITLE_ID];
74 75
75 LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, desc.title_id); 76 LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, desc.title_id);
76 77
77 if (desc.supplier == nullptr) 78 if (desc.supplier == nullptr) {
78 return nullptr; 79 return nullptr;
80 }
79 81
80 const auto dir = desc.supplier(); 82 const auto dir = desc.supplier();
81 83
82 if (dir == nullptr) 84 if (dir == nullptr) {
83 return nullptr; 85 return nullptr;
86 }
84 87
85 const auto romfs = CreateRomFS(dir); 88 const auto romfs = CreateRomFS(dir);
86 89
87 if (romfs == nullptr) 90 if (romfs == nullptr) {
88 return nullptr; 91 return nullptr;
92 }
89 93
90 LOG_INFO(Service_FS, " - System archive generation successful!"); 94 LOG_INFO(Service_FS, " - System archive generation successful!");
91 return romfs; 95 return romfs;
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp
index afaea4135..6423e5089 100755
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -89,7 +89,8 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN
89 std::min(configured_name.name.size(), configured_zone.size())); 89 std::min(configured_name.name.size(), configured_zone.size()));
90 } 90 }
91 91
92 ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone!"); 92 ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
93 configured_name.name.data());
93 94
94 return configured_name; 95 return configured_name;
95} 96}
diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp
index 96530dce5..67969aa3f 100755
--- a/src/core/hle/service/glue/time/time_zone_binary.cpp
+++ b/src/core/hle/service/glue/time/time_zone_binary.cpp
@@ -61,6 +61,16 @@ Result MountTimeZoneBinary(Core::System& system) {
61 g_time_zone_binary_romfs = FileSys::ExtractRomFS(nca->GetRomFS()); 61 g_time_zone_binary_romfs = FileSys::ExtractRomFS(nca->GetRomFS());
62 } 62 }
63 63
64 if (g_time_zone_binary_romfs) {
65 // Validate that the romfs is readable, using invalid firmware keys can cause this to get
66 // set but the files to be garbage. In that case, we want to hit the next path and
67 // synthesise them instead.
68 Service::PSC::Time::LocationName name{"Etc/GMT"};
69 if (!IsTimeZoneBinaryValid(name)) {
70 ResetTimeZoneBinary();
71 }
72 }
73
64 if (!g_time_zone_binary_romfs) { 74 if (!g_time_zone_binary_romfs) {
65 g_time_zone_binary_romfs = FileSys::ExtractRomFS( 75 g_time_zone_binary_romfs = FileSys::ExtractRomFS(
66 FileSys::SystemArchive::SynthesizeSystemArchive(TimeZoneBinaryId)); 76 FileSys::SystemArchive::SynthesizeSystemArchive(TimeZoneBinaryId));
@@ -102,6 +112,7 @@ bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) {
102 112
103 auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)}; 113 auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)};
104 if (!vfs_file) { 114 if (!vfs_file) {
115 LOG_INFO(Service_Time, "Could not find timezone file {}", path);
105 return false; 116 return false;
106 } 117 }
107 return vfs_file->GetSize() != 0; 118 return vfs_file->GetSize() != 0;
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 1db44d504..4b046a1f8 100755
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -1093,6 +1093,20 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
1093 [&] { rasterizer = true; }); 1093 [&] { rasterizer = true; });
1094 if (rasterizer) { 1094 if (rasterizer) {
1095 impl->InvalidateGPUMemory(ptr, size); 1095 impl->InvalidateGPUMemory(ptr, size);
1096
1097 const auto type = impl->current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type();
1098 if (type == Common::PageType::RasterizerCachedMemory) {
1099 // Check if device mapped. If not, this bugged and we can unmark.
1100 DAddr addr{};
1101 Common::ScratchBuffer<u32> buffer;
1102 impl->gpu_device_memory->ApplyOpOnPointer(ptr, buffer,
1103 [&](DAddr address) { addr = address; });
1104
1105 if (addr == 0) {
1106 LOG_ERROR(HW_Memory, "Fixing unmapped cached region {:#x}", GetInteger(vaddr));
1107 impl->RasterizerMarkRegionCached(GetInteger(vaddr), size, false);
1108 }
1109 }
1096 } 1110 }
1097 1111
1098#ifdef __linux__ 1112#ifdef __linux__
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 74fd10286..61b1e85bf 100755
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1546,7 +1546,10 @@ void BufferCache<P>::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer,
1546 std::span<const u8> upload_span; 1546 std::span<const u8> upload_span;
1547 const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; 1547 const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
1548 if (IsRangeGranular(device_addr, copy.size)) { 1548 if (IsRangeGranular(device_addr, copy.size)) {
1549 upload_span = std::span(device_memory.GetPointer<u8>(device_addr), copy.size); 1549 auto* const ptr = device_memory.GetPointer<u8>(device_addr);
1550 if (ptr != nullptr) {
1551 upload_span = std::span(ptr, copy.size);
1552 }
1550 } else { 1553 } else {
1551 if (immediate_buffer.empty()) { 1554 if (immediate_buffer.empty()) {
1552 immediate_buffer = ImmediateBuffer(largest_copy); 1555 immediate_buffer = ImmediateBuffer(largest_copy);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 18bbfc348..1b3a6916f 100755
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -243,10 +243,12 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
243 const u64 size_in_bytes{Tegra::Texture::CalculateSize( 243 const u64 size_in_bytes{Tegra::Texture::CalculateSize(
244 true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; 244 true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
245 const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)}; 245 const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
246 const std::span<const u8> input_data(host_ptr, size_in_bytes); 246 if (host_ptr != nullptr) {
247 Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, 247 const std::span<const u8> input_data(host_ptr, size_in_bytes);
248 framebuffer.width, framebuffer.height, 1, block_height_log2, 248 Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
249 0); 249 framebuffer.width, framebuffer.height, 1,
250 block_height_log2, 0);
251 }
250 252
251 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 253 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
252 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); 254 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 3c0299a85..f632005f5 100755
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -230,9 +230,11 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
230 const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel, 230 const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
231 framebuffer.stride, framebuffer.height, 231 framebuffer.stride, framebuffer.height,
232 1, block_height_log2, 0)}; 232 1, block_height_log2, 0)};
233 Tegra::Texture::UnswizzleTexture( 233 if (host_ptr != nullptr) {
234 mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size), 234 Tegra::Texture::UnswizzleTexture(
235 bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0); 235 mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size),
236 bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
237 }
236 238
237 const VkBufferImageCopy copy{ 239 const VkBufferImageCopy copy{
238 .bufferOffset = image_offset, 240 .bufferOffset = image_offset,
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index 025d250ba..56ac24b67 100755
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -1064,8 +1064,6 @@ public:
1064 } 1064 }
1065 }); 1065 });
1066 } 1066 }
1067 auto* ptr = device_memory.GetPointer<u8>(new_query->dependant_address);
1068 ASSERT(ptr != nullptr);
1069 1067
1070 new_query->dependant_manage = must_manage_dependance; 1068 new_query->dependant_manage = must_manage_dependance;
1071 pending_flush_queries.push_back(index); 1069 pending_flush_queries.push_back(index);
@@ -1104,9 +1102,11 @@ public:
1104 tfb_streamer.Free(query->dependant_index); 1102 tfb_streamer.Free(query->dependant_index);
1105 } else { 1103 } else {
1106 u8* pointer = device_memory.GetPointer<u8>(query->dependant_address); 1104 u8* pointer = device_memory.GetPointer<u8>(query->dependant_address);
1107 u32 result; 1105 if (pointer != nullptr) {
1108 std::memcpy(&result, pointer, sizeof(u32)); 1106 u32 result;
1109 num_vertices = static_cast<u64>(result) / query->stride; 1107 std::memcpy(&result, pointer, sizeof(u32));
1108 num_vertices = static_cast<u64>(result) / query->stride;
1109 }
1110 } 1110 }
1111 query->value = [&]() -> u64 { 1111 query->value = [&]() -> u64 {
1112 switch (query->topology) { 1112 switch (query->topology) {
@@ -1360,7 +1360,9 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
1360 const auto check_value = [&](DAddr address) { 1360 const auto check_value = [&](DAddr address) {
1361 u8* ptr = impl->device_memory.GetPointer<u8>(address); 1361 u8* ptr = impl->device_memory.GetPointer<u8>(address);
1362 u64 value{}; 1362 u64 value{};
1363 std::memcpy(&value, ptr, sizeof(value)); 1363 if (ptr != nullptr) {
1364 std::memcpy(&value, ptr, sizeof(value));
1365 }
1364 return value == 0; 1366 return value == 0;
1365 }; 1367 };
1366 std::array<VideoCommon::LookupData*, 2> objects{&object_1, &object_2}; 1368 std::array<VideoCommon::LookupData*, 2> objects{&object_1, &object_2};