diff options
-rwxr-xr-x | README.md | 2 | ||||
-rwxr-xr-x | src/core/memory.cpp | 38 | ||||
-rwxr-xr-x | src/video_core/buffer_cache/buffer_base.h | 11 | ||||
-rwxr-xr-x | src/video_core/buffer_cache/buffer_cache.h | 103 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 95 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/gl_buffer_cache.h | 32 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/gl_device.cpp | 5 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/gl_device.h | 2 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/gl_rasterizer.cpp | 4 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/gl_rasterizer.h | 7 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/renderer_opengl.cpp | 88 | ||||
-rwxr-xr-x | src/video_core/renderer_opengl/renderer_opengl.h | 3 | ||||
-rwxr-xr-x | src/video_core/vulkan_common/vulkan_wrapper.cpp | 2 | ||||
-rwxr-xr-x | src/yuzu/configuration/config.cpp | 2 |
14 files changed, 152 insertions, 242 deletions
@@ -1,7 +1,7 @@ | |||
1 | yuzu emulator early access | 1 | yuzu emulator early access |
2 | ============= | 2 | ============= |
3 | 3 | ||
4 | This is the source code for early-access 1339. | 4 | This is the source code for early-access 1341. |
5 | 5 | ||
6 | ## Legal Notice | 6 | ## Legal Notice |
7 | 7 | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 961f1c028..11609682a 100755 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
@@ -195,9 +195,8 @@ struct Memory::Impl { | |||
195 | switch (type) { | 195 | switch (type) { |
196 | case Common::PageType::Unmapped: { | 196 | case Common::PageType::Unmapped: { |
197 | LOG_ERROR(HW_Memory, | 197 | LOG_ERROR(HW_Memory, |
198 | "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}) " | 198 | "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
199 | "at PC 0x{:08X}", | 199 | current_vaddr, src_addr, size); |
200 | current_vaddr, src_addr, size, system.CurrentArmInterface().GetPC()); | ||
201 | std::memset(dest_buffer, 0, copy_amount); | 200 | std::memset(dest_buffer, 0, copy_amount); |
202 | break; | 201 | break; |
203 | } | 202 | } |
@@ -241,9 +240,8 @@ struct Memory::Impl { | |||
241 | switch (type) { | 240 | switch (type) { |
242 | case Common::PageType::Unmapped: { | 241 | case Common::PageType::Unmapped: { |
243 | LOG_ERROR(HW_Memory, | 242 | LOG_ERROR(HW_Memory, |
244 | "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}) " | 243 | "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
245 | "at PC 0x{:08X}", | 244 | current_vaddr, src_addr, size); |
246 | current_vaddr, src_addr, size, system.CurrentArmInterface().GetPC()); | ||
247 | std::memset(dest_buffer, 0, copy_amount); | 245 | std::memset(dest_buffer, 0, copy_amount); |
248 | break; | 246 | break; |
249 | } | 247 | } |
@@ -293,9 +291,8 @@ struct Memory::Impl { | |||
293 | switch (type) { | 291 | switch (type) { |
294 | case Common::PageType::Unmapped: { | 292 | case Common::PageType::Unmapped: { |
295 | LOG_ERROR(HW_Memory, | 293 | LOG_ERROR(HW_Memory, |
296 | "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}) " | 294 | "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
297 | "at PC 0x{:08X}", | 295 | current_vaddr, dest_addr, size); |
298 | current_vaddr, dest_addr, size, system.CurrentArmInterface().GetPC()); | ||
299 | break; | 296 | break; |
300 | } | 297 | } |
301 | case Common::PageType::Memory: { | 298 | case Common::PageType::Memory: { |
@@ -337,9 +334,8 @@ struct Memory::Impl { | |||
337 | switch (type) { | 334 | switch (type) { |
338 | case Common::PageType::Unmapped: { | 335 | case Common::PageType::Unmapped: { |
339 | LOG_ERROR(HW_Memory, | 336 | LOG_ERROR(HW_Memory, |
340 | "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}) " | 337 | "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
341 | "at PC 0x{:08X}", | 338 | current_vaddr, dest_addr, size); |
342 | current_vaddr, dest_addr, size, system.CurrentArmInterface().GetPC()); | ||
343 | break; | 339 | break; |
344 | } | 340 | } |
345 | case Common::PageType::Memory: { | 341 | case Common::PageType::Memory: { |
@@ -387,9 +383,8 @@ struct Memory::Impl { | |||
387 | switch (type) { | 383 | switch (type) { |
388 | case Common::PageType::Unmapped: { | 384 | case Common::PageType::Unmapped: { |
389 | LOG_ERROR(HW_Memory, | 385 | LOG_ERROR(HW_Memory, |
390 | "Unmapped ZeroBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}) " | 386 | "Unmapped ZeroBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
391 | "at PC 0x{:08X}", | 387 | current_vaddr, dest_addr, size); |
392 | current_vaddr, dest_addr, size, system.CurrentArmInterface().GetPC()); | ||
393 | break; | 388 | break; |
394 | } | 389 | } |
395 | case Common::PageType::Memory: { | 390 | case Common::PageType::Memory: { |
@@ -434,9 +429,8 @@ struct Memory::Impl { | |||
434 | switch (type) { | 429 | switch (type) { |
435 | case Common::PageType::Unmapped: { | 430 | case Common::PageType::Unmapped: { |
436 | LOG_ERROR(HW_Memory, | 431 | LOG_ERROR(HW_Memory, |
437 | "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {}) " | 432 | "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", |
438 | "at PC 0x{:08X}", | 433 | current_vaddr, src_addr, size); |
439 | current_vaddr, src_addr, size, system.CurrentArmInterface().GetPC()); | ||
440 | ZeroBlock(process, dest_addr, copy_amount); | 434 | ZeroBlock(process, dest_addr, copy_amount); |
441 | break; | 435 | break; |
442 | } | 436 | } |
@@ -607,8 +601,7 @@ struct Memory::Impl { | |||
607 | } | 601 | } |
608 | switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { | 602 | switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { |
609 | case Common::PageType::Unmapped: | 603 | case Common::PageType::Unmapped: |
610 | LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr, | 604 | LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); |
611 | system.CurrentArmInterface().GetPC()); | ||
612 | return 0; | 605 | return 0; |
613 | case Common::PageType::Memory: | 606 | case Common::PageType::Memory: |
614 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | 607 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); |
@@ -645,9 +638,8 @@ struct Memory::Impl { | |||
645 | } | 638 | } |
646 | switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { | 639 | switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { |
647 | case Common::PageType::Unmapped: | 640 | case Common::PageType::Unmapped: |
648 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X} at PC 0x{:08X}", | 641 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, |
649 | sizeof(data) * 8, static_cast<u32>(data), vaddr, | 642 | static_cast<u32>(data), vaddr); |
650 | system.CurrentArmInterface().GetPC()); | ||
651 | return; | 643 | return; |
652 | case Common::PageType::Memory: | 644 | case Common::PageType::Memory: |
653 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | 645 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); |
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index 8a5e6a3e7..0c00ae280 100755 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h | |||
@@ -251,6 +251,16 @@ public: | |||
251 | flags &= ~BufferFlagBits::Picked; | 251 | flags &= ~BufferFlagBits::Picked; |
252 | } | 252 | } |
253 | 253 | ||
254 | /// Increases the likeliness of this being a stream buffer | ||
255 | void IncreaseStreamScore(int score) noexcept { | ||
256 | stream_score += score; | ||
257 | } | ||
258 | |||
259 | /// Returns the likeliness of this being a stream buffer | ||
260 | [[nodiscard]] int StreamScore() const noexcept { | ||
261 | return stream_score; | ||
262 | } | ||
263 | |||
254 | /// Returns true when vaddr -> vaddr+size is fully contained in the buffer | 264 | /// Returns true when vaddr -> vaddr+size is fully contained in the buffer |
255 | [[nodiscard]] bool IsInBounds(VAddr addr, u64 size) const noexcept { | 265 | [[nodiscard]] bool IsInBounds(VAddr addr, u64 size) const noexcept { |
256 | return addr >= cpu_addr && addr + size <= cpu_addr + SizeBytes(); | 266 | return addr >= cpu_addr && addr + size <= cpu_addr + SizeBytes(); |
@@ -574,6 +584,7 @@ private: | |||
574 | VAddr cpu_addr = 0; | 584 | VAddr cpu_addr = 0; |
575 | Words words; | 585 | Words words; |
576 | BufferFlagBits flags{}; | 586 | BufferFlagBits flags{}; |
587 | int stream_score = 0; | ||
577 | }; | 588 | }; |
578 | 589 | ||
579 | } // namespace VideoCommon | 590 | } // namespace VideoCommon |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index bd8507610..a296036f4 100755 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
@@ -71,6 +71,13 @@ class BufferCache { | |||
71 | 71 | ||
72 | struct Empty {}; | 72 | struct Empty {}; |
73 | 73 | ||
74 | struct OverlapResult { | ||
75 | std::vector<BufferId> ids; | ||
76 | VAddr begin; | ||
77 | VAddr end; | ||
78 | bool has_stream_leap = false; | ||
79 | }; | ||
80 | |||
74 | struct Binding { | 81 | struct Binding { |
75 | VAddr cpu_addr{}; | 82 | VAddr cpu_addr{}; |
76 | u32 size{}; | 83 | u32 size{}; |
@@ -84,7 +91,7 @@ class BufferCache { | |||
84 | }; | 91 | }; |
85 | 92 | ||
86 | public: | 93 | public: |
87 | static constexpr size_t SKIP_CACHE_SIZE = 4096; | 94 | static constexpr u32 SKIP_CACHE_SIZE = 4096; |
88 | 95 | ||
89 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer_, | 96 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer_, |
90 | Tegra::Engines::Maxwell3D& maxwell3d_, | 97 | Tegra::Engines::Maxwell3D& maxwell3d_, |
@@ -220,6 +227,10 @@ private: | |||
220 | 227 | ||
221 | [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); | 228 | [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); |
222 | 229 | ||
230 | [[nodiscard]] OverlapResult ResolveOverlaps(VAddr cpu_addr, u32 wanted_size); | ||
231 | |||
232 | void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score); | ||
233 | |||
223 | [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size); | 234 | [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size); |
224 | 235 | ||
225 | void Register(BufferId buffer_id); | 236 | void Register(BufferId buffer_id); |
@@ -988,12 +999,15 @@ BufferId BufferCache<P>::FindBuffer(VAddr cpu_addr, u32 size) { | |||
988 | } | 999 | } |
989 | 1000 | ||
990 | template <class P> | 1001 | template <class P> |
991 | BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { | 1002 | typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu_addr, |
1003 | u32 wanted_size) { | ||
1004 | static constexpr int STREAM_LEAP_THRESHOLD = 16; | ||
992 | std::vector<BufferId> overlap_ids; | 1005 | std::vector<BufferId> overlap_ids; |
993 | VAddr cpu_addr_begin = cpu_addr; | 1006 | VAddr begin = cpu_addr; |
994 | VAddr cpu_addr_end = cpu_addr + wanted_size; | 1007 | VAddr end = cpu_addr + wanted_size; |
995 | for (; cpu_addr >> PAGE_BITS < Common::DivCeil(cpu_addr_end, PAGE_SIZE); | 1008 | int stream_score = 0; |
996 | cpu_addr += PAGE_SIZE) { | 1009 | bool has_stream_leap = false; |
1010 | for (; cpu_addr >> PAGE_BITS < Common::DivCeil(end, PAGE_SIZE); cpu_addr += PAGE_SIZE) { | ||
997 | const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS]; | 1011 | const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS]; |
998 | if (!overlap_id) { | 1012 | if (!overlap_id) { |
999 | continue; | 1013 | continue; |
@@ -1002,38 +1016,63 @@ BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { | |||
1002 | if (overlap.IsPicked()) { | 1016 | if (overlap.IsPicked()) { |
1003 | continue; | 1017 | continue; |
1004 | } | 1018 | } |
1005 | overlap.Pick(); | ||
1006 | overlap_ids.push_back(overlap_id); | 1019 | overlap_ids.push_back(overlap_id); |
1020 | overlap.Pick(); | ||
1007 | const VAddr overlap_cpu_addr = overlap.CpuAddr(); | 1021 | const VAddr overlap_cpu_addr = overlap.CpuAddr(); |
1008 | if (overlap_cpu_addr < cpu_addr_begin) { | 1022 | if (overlap_cpu_addr < begin) { |
1009 | cpu_addr = cpu_addr_begin = overlap_cpu_addr; | 1023 | cpu_addr = begin = overlap_cpu_addr; |
1024 | } | ||
1025 | end = std::max(end, overlap_cpu_addr + overlap.SizeBytes()); | ||
1026 | |||
1027 | stream_score += overlap.StreamScore(); | ||
1028 | if (stream_score > STREAM_LEAP_THRESHOLD && !has_stream_leap) { | ||
1029 | // When this memory region has been joined a bunch of times, we assume it's being used | ||
1030 | // as a stream buffer. Increase the size to skip constantly recreating buffers. | ||
1031 | has_stream_leap = true; | ||
1032 | end += PAGE_SIZE * 256; | ||
1010 | } | 1033 | } |
1011 | cpu_addr_end = std::max(cpu_addr_end, overlap_cpu_addr + overlap.SizeBytes()); | ||
1012 | } | 1034 | } |
1013 | const u32 size = static_cast<u32>(cpu_addr_end - cpu_addr_begin); | 1035 | return OverlapResult{ |
1014 | const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, cpu_addr_begin, size); | 1036 | .ids = std::move(overlap_ids), |
1015 | Buffer& new_buffer = slot_buffers[new_buffer_id]; | 1037 | .begin = begin, |
1016 | 1038 | .end = end, | |
1017 | for (const BufferId overlap_id : overlap_ids) { | 1039 | .has_stream_leap = has_stream_leap, |
1018 | Buffer& overlap = slot_buffers[overlap_id]; | 1040 | }; |
1019 | overlap.Unpick(); | 1041 | } |
1020 | 1042 | ||
1021 | std::vector<BufferCopy> copies; | 1043 | template <class P> |
1022 | const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr(); | 1044 | void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, |
1023 | overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) { | 1045 | bool accumulate_stream_score) { |
1024 | copies.push_back(BufferCopy{ | 1046 | Buffer& new_buffer = slot_buffers[new_buffer_id]; |
1025 | .src_offset = begin, | 1047 | Buffer& overlap = slot_buffers[overlap_id]; |
1026 | .dst_offset = dst_base_offset + begin, | 1048 | if (accumulate_stream_score) { |
1027 | .size = range_size, | 1049 | new_buffer.IncreaseStreamScore(overlap.StreamScore() + 1); |
1028 | }); | 1050 | } |
1029 | new_buffer.UnmarkRegionAsCpuModified(begin, range_size); | 1051 | std::vector<BufferCopy> copies; |
1030 | new_buffer.MarkRegionAsGpuModified(begin, range_size); | 1052 | const size_t dst_base_offset = overlap.CpuAddr() - new_buffer.CpuAddr(); |
1053 | overlap.ForEachDownloadRange([&](u64 begin, u64 range_size) { | ||
1054 | copies.push_back(BufferCopy{ | ||
1055 | .src_offset = begin, | ||
1056 | .dst_offset = dst_base_offset + begin, | ||
1057 | .size = range_size, | ||
1031 | }); | 1058 | }); |
1032 | if (!copies.empty()) { | 1059 | new_buffer.UnmarkRegionAsCpuModified(begin, range_size); |
1033 | runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); | 1060 | new_buffer.MarkRegionAsGpuModified(begin, range_size); |
1034 | } | 1061 | }); |
1035 | ReplaceBufferDownloads(overlap_id, new_buffer_id); | 1062 | if (!copies.empty()) { |
1036 | DeleteBuffer(overlap_id); | 1063 | runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); |
1064 | } | ||
1065 | ReplaceBufferDownloads(overlap_id, new_buffer_id); | ||
1066 | DeleteBuffer(overlap_id); | ||
1067 | } | ||
1068 | |||
1069 | template <class P> | ||
1070 | BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { | ||
1071 | const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size); | ||
1072 | const u32 size = static_cast<u32>(overlap.end - overlap.begin); | ||
1073 | const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size); | ||
1074 | for (const BufferId overlap_id : overlap.ids) { | ||
1075 | JoinOverlap(new_buffer_id, overlap_id, !overlap.has_stream_leap); | ||
1037 | } | 1076 | } |
1038 | Register(new_buffer_id); | 1077 | Register(new_buffer_id); |
1039 | return new_buffer_id; | 1078 | return new_buffer_id; |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 889ad6c56..6da3906a4 100755 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
@@ -7,10 +7,6 @@ | |||
7 | #include "video_core/buffer_cache/buffer_cache.h" | 7 | #include "video_core/buffer_cache/buffer_cache.h" |
8 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 8 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
9 | #include "video_core/renderer_opengl/gl_device.h" | 9 | #include "video_core/renderer_opengl/gl_device.h" |
10 | #include "video_core/vulkan_common/vulkan_device.h" | ||
11 | #include "video_core/vulkan_common/vulkan_instance.h" | ||
12 | #include "video_core/vulkan_common/vulkan_library.h" | ||
13 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
14 | 10 | ||
15 | namespace OpenGL { | 11 | namespace OpenGL { |
16 | namespace { | 12 | namespace { |
@@ -36,13 +32,8 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rast | |||
36 | buffer.Create(); | 32 | buffer.Create(); |
37 | const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); | 33 | const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); |
38 | glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data()); | 34 | glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data()); |
39 | if (runtime.device.UseAssemblyShaders()) { | 35 | glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW); |
40 | CreateMemoryObjects(runtime); | 36 | |
41 | glNamedBufferStorageMemEXT(buffer.handle, SizeBytes(), memory_commit.ExportOpenGLHandle(), | ||
42 | memory_commit.Offset()); | ||
43 | } else { | ||
44 | glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW); | ||
45 | } | ||
46 | if (runtime.has_unified_vertex_buffers) { | 37 | if (runtime.has_unified_vertex_buffers) { |
47 | glGetNamedBufferParameterui64vNV(buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &address); | 38 | glGetNamedBufferParameterui64vNV(buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &address); |
48 | } | 39 | } |
@@ -71,61 +62,30 @@ void Buffer::MakeResident(GLenum access) noexcept { | |||
71 | glMakeNamedBufferResidentNV(buffer.handle, access); | 62 | glMakeNamedBufferResidentNV(buffer.handle, access); |
72 | } | 63 | } |
73 | 64 | ||
74 | GLuint Buffer::SubBuffer(u32 offset) { | 65 | BufferCacheRuntime::BufferCacheRuntime(const Device& device_) |
75 | if (offset == 0) { | 66 | : device{device_}, has_fast_buffer_sub_data{device.HasFastBufferSubData()}, |
76 | return buffer.handle; | 67 | use_assembly_shaders{device.UseAssemblyShaders()}, |
77 | } | 68 | has_unified_vertex_buffers{device.HasVertexBufferUnifiedMemory()}, |
78 | for (const auto& [sub_buffer, sub_offset] : subs) { | 69 | stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} { |
79 | if (sub_offset == offset) { | ||
80 | return sub_buffer.handle; | ||
81 | } | ||
82 | } | ||
83 | OGLBuffer sub_buffer; | ||
84 | sub_buffer.Create(); | ||
85 | glNamedBufferStorageMemEXT(sub_buffer.handle, SizeBytes() - offset, | ||
86 | memory_commit.ExportOpenGLHandle(), memory_commit.Offset() + offset); | ||
87 | return subs.emplace_back(std::move(sub_buffer), offset).first.handle; | ||
88 | } | ||
89 | |||
90 | void Buffer::CreateMemoryObjects(BufferCacheRuntime& runtime) { | ||
91 | auto& allocator = runtime.vulkan_memory_allocator; | ||
92 | auto& device = runtime.vulkan_device->GetLogical(); | ||
93 | auto vulkan_buffer = device.CreateBuffer(VkBufferCreateInfo{ | ||
94 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
95 | .pNext = nullptr, | ||
96 | .flags = 0, | ||
97 | .size = SizeBytes(), | ||
98 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | ||
99 | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | | ||
100 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | | ||
101 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | | ||
102 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, | ||
103 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
104 | .queueFamilyIndexCount = 0, | ||
105 | .pQueueFamilyIndices = nullptr, | ||
106 | }); | ||
107 | const VkMemoryRequirements requirements = device.GetBufferMemoryRequirements(*vulkan_buffer); | ||
108 | memory_commit = allocator->Commit(requirements, Vulkan::MemoryUsage::DeviceLocal); | ||
109 | } | ||
110 | |||
111 | BufferCacheRuntime::BufferCacheRuntime(const Device& device_, const Vulkan::Device* vulkan_device_, | ||
112 | Vulkan::MemoryAllocator* vulkan_memory_allocator_) | ||
113 | : device{device_}, vulkan_device{vulkan_device_}, | ||
114 | vulkan_memory_allocator{vulkan_memory_allocator_}, | ||
115 | stream_buffer{device.HasFastBufferSubData() ? std::nullopt | ||
116 | : std::make_optional<StreamBuffer>()} { | ||
117 | GLint gl_max_attributes; | 70 | GLint gl_max_attributes; |
118 | glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes); | 71 | glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes); |
119 | max_attributes = static_cast<u32>(gl_max_attributes); | 72 | max_attributes = static_cast<u32>(gl_max_attributes); |
120 | use_assembly_shaders = device.UseAssemblyShaders(); | ||
121 | has_unified_vertex_buffers = device.HasVertexBufferUnifiedMemory(); | ||
122 | |||
123 | for (auto& stage_uniforms : fast_uniforms) { | 73 | for (auto& stage_uniforms : fast_uniforms) { |
124 | for (OGLBuffer& buffer : stage_uniforms) { | 74 | for (OGLBuffer& buffer : stage_uniforms) { |
125 | buffer.Create(); | 75 | buffer.Create(); |
126 | glNamedBufferData(buffer.handle, BufferCache::SKIP_CACHE_SIZE, nullptr, GL_STREAM_DRAW); | 76 | glNamedBufferData(buffer.handle, BufferCache::SKIP_CACHE_SIZE, nullptr, GL_STREAM_DRAW); |
127 | } | 77 | } |
128 | } | 78 | } |
79 | for (auto& stage_uniforms : copy_uniforms) { | ||
80 | for (OGLBuffer& buffer : stage_uniforms) { | ||
81 | buffer.Create(); | ||
82 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); | ||
83 | } | ||
84 | } | ||
85 | for (OGLBuffer& buffer : copy_compute_uniforms) { | ||
86 | buffer.Create(); | ||
87 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); | ||
88 | } | ||
129 | } | 89 | } |
130 | 90 | ||
131 | void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, | 91 | void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, |
@@ -167,8 +127,14 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, | |||
167 | void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, | 127 | void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, |
168 | u32 offset, u32 size) { | 128 | u32 offset, u32 size) { |
169 | if (use_assembly_shaders) { | 129 | if (use_assembly_shaders) { |
170 | const GLuint sub_buffer = buffer.SubBuffer(offset); | 130 | GLuint handle; |
171 | glBindBufferRangeNV(PABO_LUT[stage], binding_index, sub_buffer, 0, | 131 | if (offset != 0) { |
132 | handle = copy_uniforms[stage][binding_index].handle; | ||
133 | glCopyNamedBufferSubData(buffer.Handle(), handle, offset, 0, size); | ||
134 | } else { | ||
135 | handle = buffer.Handle(); | ||
136 | } | ||
137 | glBindBufferRangeNV(PABO_LUT[stage], binding_index, handle, 0, | ||
172 | static_cast<GLsizeiptr>(size)); | 138 | static_cast<GLsizeiptr>(size)); |
173 | } else { | 139 | } else { |
174 | const GLuint base_binding = device.GetBaseBindings(stage).uniform_buffer; | 140 | const GLuint base_binding = device.GetBaseBindings(stage).uniform_buffer; |
@@ -181,8 +147,15 @@ void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buff | |||
181 | void BufferCacheRuntime::BindComputeUniformBuffer(u32 binding_index, Buffer& buffer, u32 offset, | 147 | void BufferCacheRuntime::BindComputeUniformBuffer(u32 binding_index, Buffer& buffer, u32 offset, |
182 | u32 size) { | 148 | u32 size) { |
183 | if (use_assembly_shaders) { | 149 | if (use_assembly_shaders) { |
184 | glBindBufferRangeNV(GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV, binding_index, | 150 | GLuint handle; |
185 | buffer.SubBuffer(offset), 0, static_cast<GLsizeiptr>(size)); | 151 | if (offset != 0) { |
152 | handle = copy_compute_uniforms[binding_index].handle; | ||
153 | glCopyNamedBufferSubData(buffer.Handle(), handle, offset, 0, size); | ||
154 | } else { | ||
155 | handle = buffer.Handle(); | ||
156 | } | ||
157 | glBindBufferRangeNV(GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV, binding_index, handle, 0, | ||
158 | static_cast<GLsizeiptr>(size)); | ||
186 | } else { | 159 | } else { |
187 | glBindBufferRange(GL_UNIFORM_BUFFER, binding_index, buffer.Handle(), | 160 | glBindBufferRange(GL_UNIFORM_BUFFER, binding_index, buffer.Handle(), |
188 | static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size)); | 161 | static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size)); |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index f4d8871a9..d8b20a9af 100755 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
@@ -15,13 +15,6 @@ | |||
15 | #include "video_core/renderer_opengl/gl_device.h" | 15 | #include "video_core/renderer_opengl/gl_device.h" |
16 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 16 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
17 | #include "video_core/renderer_opengl/gl_stream_buffer.h" | 17 | #include "video_core/renderer_opengl/gl_stream_buffer.h" |
18 | #include "video_core/vulkan_common/vulkan_device.h" | ||
19 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
20 | |||
21 | namespace Vulkan { | ||
22 | class Device; | ||
23 | class MemoryAllocator; | ||
24 | } // namespace Vulkan | ||
25 | 18 | ||
26 | namespace OpenGL { | 19 | namespace OpenGL { |
27 | 20 | ||
@@ -39,8 +32,6 @@ public: | |||
39 | 32 | ||
40 | void MakeResident(GLenum access) noexcept; | 33 | void MakeResident(GLenum access) noexcept; |
41 | 34 | ||
42 | [[nodiscard]] GLuint SubBuffer(u32 offset); | ||
43 | |||
44 | [[nodiscard]] GLuint64EXT HostGpuAddr() const noexcept { | 35 | [[nodiscard]] GLuint64EXT HostGpuAddr() const noexcept { |
45 | return address; | 36 | return address; |
46 | } | 37 | } |
@@ -50,13 +41,9 @@ public: | |||
50 | } | 41 | } |
51 | 42 | ||
52 | private: | 43 | private: |
53 | void CreateMemoryObjects(BufferCacheRuntime& runtime); | ||
54 | |||
55 | GLuint64EXT address = 0; | 44 | GLuint64EXT address = 0; |
56 | Vulkan::MemoryCommit memory_commit; | ||
57 | OGLBuffer buffer; | 45 | OGLBuffer buffer; |
58 | GLenum current_residency_access = GL_NONE; | 46 | GLenum current_residency_access = GL_NONE; |
59 | std::vector<std::pair<OGLBuffer, u32>> subs; | ||
60 | }; | 47 | }; |
61 | 48 | ||
62 | class BufferCacheRuntime { | 49 | class BufferCacheRuntime { |
@@ -65,8 +52,7 @@ class BufferCacheRuntime { | |||
65 | public: | 52 | public: |
66 | static constexpr u8 INVALID_BINDING = std::numeric_limits<u8>::max(); | 53 | static constexpr u8 INVALID_BINDING = std::numeric_limits<u8>::max(); |
67 | 54 | ||
68 | explicit BufferCacheRuntime(const Device& device_, const Vulkan::Device* vulkan_device_, | 55 | explicit BufferCacheRuntime(const Device& device_); |
69 | Vulkan::MemoryAllocator* vulkan_memory_allocator_); | ||
70 | 56 | ||
71 | void CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, | 57 | void CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, |
72 | std::span<const VideoCommon::BufferCopy> copies); | 58 | std::span<const VideoCommon::BufferCopy> copies); |
@@ -127,7 +113,7 @@ public: | |||
127 | } | 113 | } |
128 | 114 | ||
129 | [[nodiscard]] bool HasFastBufferSubData() const noexcept { | 115 | [[nodiscard]] bool HasFastBufferSubData() const noexcept { |
130 | return device.HasFastBufferSubData(); | 116 | return has_fast_buffer_sub_data; |
131 | } | 117 | } |
132 | 118 | ||
133 | private: | 119 | private: |
@@ -138,18 +124,22 @@ private: | |||
138 | }; | 124 | }; |
139 | 125 | ||
140 | const Device& device; | 126 | const Device& device; |
141 | const Vulkan::Device* vulkan_device; | ||
142 | Vulkan::MemoryAllocator* vulkan_memory_allocator; | ||
143 | std::optional<StreamBuffer> stream_buffer; | ||
144 | |||
145 | u32 max_attributes = 0; | ||
146 | 127 | ||
128 | bool has_fast_buffer_sub_data = false; | ||
147 | bool use_assembly_shaders = false; | 129 | bool use_assembly_shaders = false; |
148 | bool has_unified_vertex_buffers = false; | 130 | bool has_unified_vertex_buffers = false; |
149 | 131 | ||
132 | u32 max_attributes = 0; | ||
133 | |||
134 | std::optional<StreamBuffer> stream_buffer; | ||
135 | |||
150 | std::array<std::array<OGLBuffer, VideoCommon::NUM_GRAPHICS_UNIFORM_BUFFERS>, | 136 | std::array<std::array<OGLBuffer, VideoCommon::NUM_GRAPHICS_UNIFORM_BUFFERS>, |
151 | VideoCommon::NUM_STAGES> | 137 | VideoCommon::NUM_STAGES> |
152 | fast_uniforms; | 138 | fast_uniforms; |
139 | std::array<std::array<OGLBuffer, VideoCommon::NUM_GRAPHICS_UNIFORM_BUFFERS>, | ||
140 | VideoCommon::NUM_STAGES> | ||
141 | copy_uniforms; | ||
142 | std::array<OGLBuffer, VideoCommon::NUM_COMPUTE_UNIFORM_BUFFERS> copy_compute_uniforms; | ||
153 | 143 | ||
154 | u32 index_buffer_offset = 0; | 144 | u32 index_buffer_offset = 0; |
155 | }; | 145 | }; |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 7310185e6..703391ca5 100755 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
@@ -197,7 +197,7 @@ bool IsASTCSupported() { | |||
197 | } | 197 | } |
198 | } // Anonymous namespace | 198 | } // Anonymous namespace |
199 | 199 | ||
200 | Device::Device(bool has_vulkan_instance) { | 200 | Device::Device() { |
201 | if (!GLAD_GL_VERSION_4_3) { | 201 | if (!GLAD_GL_VERSION_4_3) { |
202 | LOG_ERROR(Render_OpenGL, "OpenGL 4.3 is not available"); | 202 | LOG_ERROR(Render_OpenGL, "OpenGL 4.3 is not available"); |
203 | throw std::runtime_error{"Insufficient version"}; | 203 | throw std::runtime_error{"Insufficient version"}; |
@@ -246,8 +246,7 @@ Device::Device(bool has_vulkan_instance) { | |||
246 | 246 | ||
247 | use_assembly_shaders = Settings::values.use_assembly_shaders.GetValue() && | 247 | use_assembly_shaders = Settings::values.use_assembly_shaders.GetValue() && |
248 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && | 248 | GLAD_GL_NV_gpu_program5 && GLAD_GL_NV_compute_program5 && |
249 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2 && | 249 | GLAD_GL_NV_transform_feedback && GLAD_GL_NV_transform_feedback2; |
250 | has_vulkan_instance; | ||
251 | 250 | ||
252 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue(); | 251 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue(); |
253 | 252 | ||
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 21a38544f..9e620f603 100755 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
@@ -19,7 +19,7 @@ public: | |||
19 | u32 image{}; | 19 | u32 image{}; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | explicit Device(bool has_vulkan_instance); | 22 | explicit Device(); |
23 | explicit Device(std::nullptr_t); | 23 | explicit Device(std::nullptr_t); |
24 | 24 | ||
25 | u32 GetMaxUniformBuffers(Tegra::Engines::ShaderType shader_type) const noexcept { | 25 | u32 GetMaxUniformBuffers(Tegra::Engines::ShaderType shader_type) const noexcept { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 3e90e6481..8298d6787 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
@@ -170,8 +170,6 @@ ImageViewType ImageViewTypeFromEntry(const ImageEntry& entry) { | |||
170 | 170 | ||
171 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 171 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
172 | Core::Memory::Memory& cpu_memory_, const Device& device_, | 172 | Core::Memory::Memory& cpu_memory_, const Device& device_, |
173 | const Vulkan::Device* vulkan_device, | ||
174 | Vulkan::MemoryAllocator* vulkan_memory_allocator, | ||
175 | ScreenInfo& screen_info_, ProgramManager& program_manager_, | 173 | ScreenInfo& screen_info_, ProgramManager& program_manager_, |
176 | StateTracker& state_tracker_) | 174 | StateTracker& state_tracker_) |
177 | : RasterizerAccelerated(cpu_memory_), gpu(gpu_), maxwell3d(gpu.Maxwell3D()), | 175 | : RasterizerAccelerated(cpu_memory_), gpu(gpu_), maxwell3d(gpu.Maxwell3D()), |
@@ -179,7 +177,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
179 | screen_info(screen_info_), program_manager(program_manager_), state_tracker(state_tracker_), | 177 | screen_info(screen_info_), program_manager(program_manager_), state_tracker(state_tracker_), |
180 | texture_cache_runtime(device, program_manager, state_tracker), | 178 | texture_cache_runtime(device, program_manager, state_tracker), |
181 | texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory), | 179 | texture_cache(texture_cache_runtime, *this, maxwell3d, kepler_compute, gpu_memory), |
182 | buffer_cache_runtime(device, vulkan_device, vulkan_memory_allocator), | 180 | buffer_cache_runtime(device), |
183 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), | 181 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), |
184 | shader_cache(*this, emu_window_, gpu, maxwell3d, kepler_compute, gpu_memory, device), | 182 | shader_cache(*this, emu_window_, gpu, maxwell3d, kepler_compute, gpu_memory, device), |
185 | query_cache(*this, maxwell3d, gpu_memory), | 183 | query_cache(*this, maxwell3d, gpu_memory), |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index b1094075a..9730544d9 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
@@ -46,11 +46,6 @@ namespace Tegra { | |||
46 | class MemoryManager; | 46 | class MemoryManager; |
47 | } | 47 | } |
48 | 48 | ||
49 | namespace Vulkan { | ||
50 | class Device; | ||
51 | class MemoryAllocator; | ||
52 | } // namespace Vulkan | ||
53 | |||
54 | namespace OpenGL { | 49 | namespace OpenGL { |
55 | 50 | ||
56 | struct ScreenInfo; | 51 | struct ScreenInfo; |
@@ -67,8 +62,6 @@ class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { | |||
67 | public: | 62 | public: |
68 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 63 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
69 | Core::Memory::Memory& cpu_memory_, const Device& device_, | 64 | Core::Memory::Memory& cpu_memory_, const Device& device_, |
70 | const Vulkan::Device* vulkan_device, | ||
71 | Vulkan::MemoryAllocator* vulkan_memory_allocator, | ||
72 | ScreenInfo& screen_info_, ProgramManager& program_manager_, | 65 | ScreenInfo& screen_info_, ProgramManager& program_manager_, |
73 | StateTracker& state_tracker_); | 66 | StateTracker& state_tracker_); |
74 | ~RasterizerOpenGL() override; | 67 | ~RasterizerOpenGL() override; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8fcb86581..9d2acd4d9 100755 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
@@ -27,11 +27,6 @@ | |||
27 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 27 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
28 | #include "video_core/renderer_opengl/renderer_opengl.h" | 28 | #include "video_core/renderer_opengl/renderer_opengl.h" |
29 | #include "video_core/textures/decoders.h" | 29 | #include "video_core/textures/decoders.h" |
30 | #include "video_core/vulkan_common/vulkan_debug_callback.h" | ||
31 | #include "video_core/vulkan_common/vulkan_device.h" | ||
32 | #include "video_core/vulkan_common/vulkan_instance.h" | ||
33 | #include "video_core/vulkan_common/vulkan_library.h" | ||
34 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
35 | 30 | ||
36 | namespace OpenGL { | 31 | namespace OpenGL { |
37 | namespace { | 32 | namespace { |
@@ -127,93 +122,16 @@ void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severit | |||
127 | break; | 122 | break; |
128 | } | 123 | } |
129 | } | 124 | } |
130 | |||
131 | Vulkan::vk::PhysicalDevice FindPhysicalDevice(Vulkan::vk::Instance& instance) { | ||
132 | using namespace Vulkan; | ||
133 | using UUID = std::array<GLubyte, GL_UUID_SIZE_EXT>; | ||
134 | |||
135 | GLint num_device_uuids; | ||
136 | glGetIntegerv(GL_NUM_DEVICE_UUIDS_EXT, &num_device_uuids); | ||
137 | std::vector<UUID> device_uuids(num_device_uuids); | ||
138 | for (GLint index = 0; index < num_device_uuids; ++index) { | ||
139 | glGetUnsignedBytei_vEXT(GL_DEVICE_UUID_EXT, 0, device_uuids[index].data()); | ||
140 | } | ||
141 | UUID driver_uuid; | ||
142 | glGetUnsignedBytevEXT(GL_DRIVER_UUID_EXT, driver_uuid.data()); | ||
143 | |||
144 | for (const VkPhysicalDevice raw_physical_device : instance.EnumeratePhysicalDevices()) { | ||
145 | VkPhysicalDeviceIDProperties device_id_properties{}; | ||
146 | device_id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; | ||
147 | |||
148 | VkPhysicalDeviceProperties2KHR properties{ | ||
149 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, | ||
150 | .pNext = &device_id_properties, | ||
151 | .properties{}, | ||
152 | }; | ||
153 | vk::PhysicalDevice physical_device(raw_physical_device, instance.Dispatch()); | ||
154 | physical_device.GetProperties2KHR(properties); | ||
155 | if (!std::ranges::equal(device_id_properties.driverUUID, driver_uuid)) { | ||
156 | continue; | ||
157 | } | ||
158 | const auto it = | ||
159 | std::ranges::find_if(device_uuids, [&device_id_properties, driver_uuid](UUID uuid) { | ||
160 | return std::ranges::equal(device_id_properties.deviceUUID, uuid); | ||
161 | }); | ||
162 | if (it != device_uuids.end()) { | ||
163 | return physical_device; | ||
164 | } | ||
165 | } | ||
166 | throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); | ||
167 | } | ||
168 | } // Anonymous namespace | 125 | } // Anonymous namespace |
169 | 126 | ||
170 | struct VulkanObjects { | ||
171 | static std::unique_ptr<VulkanObjects> TryCreate() { | ||
172 | if (!GLAD_GL_EXT_memory_object) { | ||
173 | // Interop is not present | ||
174 | return nullptr; | ||
175 | } | ||
176 | const std::string_view vendor{reinterpret_cast<const char*>(glGetString(GL_VENDOR))}; | ||
177 | if (vendor == "ATI Technologies Inc.") { | ||
178 | // Avoid using GL_EXT_memory_object on AMD, as it makes the GL driver crash | ||
179 | return nullptr; | ||
180 | } | ||
181 | if (!Settings::values.use_assembly_shaders.GetValue()) { | ||
182 | // We only need interop when assembly shaders are enabled | ||
183 | return nullptr; | ||
184 | } | ||
185 | #ifdef __linux__ | ||
186 | LOG_WARNING(Render_OpenGL, "Interop doesn't work on Linux at the moment"); | ||
187 | return nullptr; | ||
188 | #endif | ||
189 | try { | ||
190 | return std::make_unique<VulkanObjects>(); | ||
191 | } catch (const Vulkan::vk::Exception& exception) { | ||
192 | LOG_ERROR(Render_OpenGL, "Failed to initialize Vulkan objects with error: {}", | ||
193 | exception.what()); | ||
194 | return nullptr; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | Common::DynamicLibrary library{Vulkan::OpenLibrary()}; | ||
199 | Vulkan::vk::InstanceDispatch dld; | ||
200 | Vulkan::vk::Instance instance{Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1)}; | ||
201 | Vulkan::Device device{*instance, FindPhysicalDevice(instance), nullptr, dld}; | ||
202 | Vulkan::MemoryAllocator memory_allocator{device, true}; | ||
203 | }; | ||
204 | |||
205 | RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, | 127 | RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, |
206 | Core::Frontend::EmuWindow& emu_window_, | 128 | Core::Frontend::EmuWindow& emu_window_, |
207 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 129 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, |
208 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | 130 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
209 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, | 131 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, |
210 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, | 132 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, state_tracker{gpu}, |
211 | vulkan_objects{VulkanObjects::TryCreate()}, device{vulkan_objects != nullptr}, | 133 | program_manager{device}, |
212 | state_tracker{gpu}, program_manager{device}, | 134 | rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) { |
213 | rasterizer(emu_window, gpu, cpu_memory, device, | ||
214 | vulkan_objects ? &vulkan_objects->device : nullptr, | ||
215 | vulkan_objects ? &vulkan_objects->memory_allocator : nullptr, screen_info, | ||
216 | program_manager, state_tracker) { | ||
217 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { | 135 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { |
218 | glEnable(GL_DEBUG_OUTPUT); | 136 | glEnable(GL_DEBUG_OUTPUT); |
219 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | 137 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index f210190dd..cc19a110f 100755 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
@@ -38,8 +38,6 @@ class GPU; | |||
38 | 38 | ||
39 | namespace OpenGL { | 39 | namespace OpenGL { |
40 | 40 | ||
41 | struct VulkanObjects; | ||
42 | |||
43 | /// Structure used for storing information about the textures for the Switch screen | 41 | /// Structure used for storing information about the textures for the Switch screen |
44 | struct TextureInfo { | 42 | struct TextureInfo { |
45 | OGLTexture resource; | 43 | OGLTexture resource; |
@@ -101,7 +99,6 @@ private: | |||
101 | Core::Memory::Memory& cpu_memory; | 99 | Core::Memory::Memory& cpu_memory; |
102 | Tegra::GPU& gpu; | 100 | Tegra::GPU& gpu; |
103 | 101 | ||
104 | std::unique_ptr<VulkanObjects> vulkan_objects; | ||
105 | Device device; | 102 | Device device; |
106 | StateTracker state_tracker; | 103 | StateTracker state_tracker; |
107 | ProgramManager program_manager; | 104 | ProgramManager program_manager; |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 311d3d22d..2aa0ffbe6 100755 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
@@ -787,7 +787,7 @@ DeviceMemory Device::AllocateMemory(const VkMemoryAllocateInfo& ai) const { | |||
787 | } | 787 | } |
788 | 788 | ||
789 | VkMemoryRequirements Device::GetBufferMemoryRequirements(VkBuffer buffer, | 789 | VkMemoryRequirements Device::GetBufferMemoryRequirements(VkBuffer buffer, |
790 | void* pnext) const noexcept { | 790 | void* pnext) const noexcept { |
791 | const VkBufferMemoryRequirementsInfo2 info{ | 791 | const VkBufferMemoryRequirementsInfo2 info{ |
792 | .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, | 792 | .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, |
793 | .pNext = nullptr, | 793 | .pNext = nullptr, |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 5e4d22299..72e69cdfe 100755 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
@@ -785,7 +785,7 @@ void Config::ReadRendererValues() { | |||
785 | true); | 785 | true); |
786 | ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); | 786 | ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); |
787 | ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), | 787 | ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), |
788 | true); | 788 | false); |
789 | ReadSettingGlobal(Settings::values.use_asynchronous_shaders, | 789 | ReadSettingGlobal(Settings::values.use_asynchronous_shaders, |
790 | QStringLiteral("use_asynchronous_shaders"), false); | 790 | QStringLiteral("use_asynchronous_shaders"), false); |
791 | ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), | 791 | ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), |