diff options
Diffstat (limited to 'src')
24 files changed, 159 insertions, 159 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index ed5ce6f8a..3d795b57f 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -123,9 +123,6 @@ int EmulationSession::InstallFileToNand(std::string filename, std::string file_e | |||
| 123 | ErrorFilenameExtension = 4, | 123 | ErrorFilenameExtension = 4, |
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); | ||
| 127 | m_system.GetFileSystemController().CreateFactories(*m_vfs); | ||
| 128 | |||
| 129 | [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp; | 126 | [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp; |
| 130 | if (file_extension == "nsp") { | 127 | if (file_extension == "nsp") { |
| 131 | nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read)); | 128 | nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read)); |
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 2c6fc7657..b58a7073f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -188,7 +188,7 @@ if (UNIX AND NOT APPLE) | |||
| 188 | linux/gamemode.h | 188 | linux/gamemode.h |
| 189 | ) | 189 | ) |
| 190 | 190 | ||
| 191 | target_link_libraries(common PRIVATE gamemode) | 191 | target_link_libraries(common PRIVATE gamemode::headers) |
| 192 | endif() | 192 | endif() |
| 193 | 193 | ||
| 194 | if(ARCHITECTURE_x86_64) | 194 | if(ARCHITECTURE_x86_64) |
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 3a9ea6eb4..4bfc64f2d 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | #include <unistd.h> | 25 | #include <unistd.h> |
| 26 | #include "common/scope_exit.h" | 26 | #include "common/scope_exit.h" |
| 27 | 27 | ||
| 28 | #ifndef MAP_NORESERVE | ||
| 29 | #define MAP_NORESERVE 0 | ||
| 30 | #endif | ||
| 31 | |||
| 28 | #endif // ^^^ Linux ^^^ | 32 | #endif // ^^^ Linux ^^^ |
| 29 | 33 | ||
| 30 | #include <mutex> | 34 | #include <mutex> |
| @@ -404,6 +408,16 @@ static void* ChooseVirtualBase(size_t virtual_size) { | |||
| 404 | #else | 408 | #else |
| 405 | 409 | ||
| 406 | static void* ChooseVirtualBase(size_t virtual_size) { | 410 | static void* ChooseVirtualBase(size_t virtual_size) { |
| 411 | #if defined(__FreeBSD__) | ||
| 412 | void* virtual_base = | ||
| 413 | mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, | ||
| 414 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0); | ||
| 415 | |||
| 416 | if (virtual_base != MAP_FAILED) { | ||
| 417 | return virtual_base; | ||
| 418 | } | ||
| 419 | #endif | ||
| 420 | |||
| 407 | return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, | 421 | return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, |
| 408 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); | 422 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); |
| 409 | } | 423 | } |
| @@ -459,24 +473,12 @@ public: | |||
| 459 | } | 473 | } |
| 460 | 474 | ||
| 461 | // Virtual memory initialization | 475 | // Virtual memory initialization |
| 462 | #if defined(__FreeBSD__) | ||
| 463 | virtual_base = | ||
| 464 | static_cast<u8*>(mmap(nullptr, virtual_size, PROT_NONE, | ||
| 465 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0)); | ||
| 466 | if (virtual_base == MAP_FAILED) { | ||
| 467 | virtual_base = static_cast<u8*>( | ||
| 468 | mmap(nullptr, virtual_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); | ||
| 469 | if (virtual_base == MAP_FAILED) { | ||
| 470 | LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); | ||
| 471 | throw std::bad_alloc{}; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | #else | ||
| 475 | virtual_base = virtual_map_base = static_cast<u8*>(ChooseVirtualBase(virtual_size)); | 476 | virtual_base = virtual_map_base = static_cast<u8*>(ChooseVirtualBase(virtual_size)); |
| 476 | if (virtual_base == MAP_FAILED) { | 477 | if (virtual_base == MAP_FAILED) { |
| 477 | LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); | 478 | LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); |
| 478 | throw std::bad_alloc{}; | 479 | throw std::bad_alloc{}; |
| 479 | } | 480 | } |
| 481 | #if defined(__linux__) | ||
| 480 | madvise(virtual_base, virtual_size, MADV_HUGEPAGE); | 482 | madvise(virtual_base, virtual_size, MADV_HUGEPAGE); |
| 481 | #endif | 483 | #endif |
| 482 | 484 | ||
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 0bca05587..cc7af2ea3 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -429,10 +429,6 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs | |||
| 429 | LOG_DEBUG(Loader, "{}", log_string); | 429 | LOG_DEBUG(Loader, "{}", log_string); |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | if (base_romfs == nullptr) { | ||
| 433 | return base_romfs; | ||
| 434 | } | ||
| 435 | |||
| 436 | auto romfs = base_romfs; | 432 | auto romfs = base_romfs; |
| 437 | 433 | ||
| 438 | // Game Updates | 434 | // Game Updates |
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp index 1eb1f439a..6de2103a0 100644 --- a/src/core/file_sys/romfs.cpp +++ b/src/core/file_sys/romfs.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <memory> | 4 | #include <memory> |
| 5 | 5 | ||
| 6 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 7 | #include "common/string_util.h" | 8 | #include "common/string_util.h" |
| 8 | #include "common/swap.h" | 9 | #include "common/swap.h" |
| @@ -101,24 +102,30 @@ void ProcessDirectory(const VirtualFile& file, std::size_t dir_offset, std::size | |||
| 101 | } // Anonymous namespace | 102 | } // Anonymous namespace |
| 102 | 103 | ||
| 103 | VirtualDir ExtractRomFS(VirtualFile file) { | 104 | VirtualDir ExtractRomFS(VirtualFile file) { |
| 105 | auto root_container = std::make_shared<VectorVfsDirectory>(); | ||
| 106 | if (!file) { | ||
| 107 | return root_container; | ||
| 108 | } | ||
| 109 | |||
| 104 | RomFSHeader header{}; | 110 | RomFSHeader header{}; |
| 105 | if (file->ReadObject(&header) != sizeof(RomFSHeader)) | 111 | if (file->ReadObject(&header) != sizeof(RomFSHeader)) { |
| 106 | return nullptr; | 112 | return root_container; |
| 113 | } | ||
| 107 | 114 | ||
| 108 | if (header.header_size != sizeof(RomFSHeader)) | 115 | if (header.header_size != sizeof(RomFSHeader)) { |
| 109 | return nullptr; | 116 | return root_container; |
| 117 | } | ||
| 110 | 118 | ||
| 111 | const u64 file_offset = header.file_meta.offset; | 119 | const u64 file_offset = header.file_meta.offset; |
| 112 | const u64 dir_offset = header.directory_meta.offset; | 120 | const u64 dir_offset = header.directory_meta.offset; |
| 113 | 121 | ||
| 114 | auto root_container = std::make_shared<VectorVfsDirectory>(); | ||
| 115 | |||
| 116 | ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root_container); | 122 | ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root_container); |
| 117 | 123 | ||
| 118 | if (auto root = root_container->GetSubdirectory(""); root) { | 124 | if (auto root = root_container->GetSubdirectory(""); root) { |
| 119 | return std::make_shared<CachedVfsDirectory>(std::move(root)); | 125 | return std::make_shared<CachedVfsDirectory>(std::move(root)); |
| 120 | } | 126 | } |
| 121 | 127 | ||
| 128 | ASSERT(false); | ||
| 122 | return nullptr; | 129 | return nullptr; |
| 123 | } | 130 | } |
| 124 | 131 | ||
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index 1bc07dae5..35e149905 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -22,7 +22,7 @@ RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader, ContentProvider& provi | |||
| 22 | : content_provider{provider}, filesystem_controller{controller} { | 22 | : content_provider{provider}, filesystem_controller{controller} { |
| 23 | // Load the RomFS from the app | 23 | // Load the RomFS from the app |
| 24 | if (app_loader.ReadRomFS(file) != Loader::ResultStatus::Success) { | 24 | if (app_loader.ReadRomFS(file) != Loader::ResultStatus::Success) { |
| 25 | LOG_ERROR(Service_FS, "Unable to read RomFS!"); | 25 | LOG_WARNING(Service_FS, "Unable to read base RomFS"); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | updatable = app_loader.IsRomFSUpdatable(); | 28 | updatable = app_loader.IsRomFSUpdatable(); |
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 47516f883..f97e5b44c 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -438,16 +438,16 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target | |||
| 438 | is_corrupted = true; | 438 | is_corrupted = true; |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | if (!is_corrupted) { | 441 | device_state = DeviceState::TagMounted; |
| 442 | mount_target = mount_target_; | ||
| 443 | |||
| 444 | if (!is_corrupted && mount_target != NFP::MountTarget::Rom) { | ||
| 442 | std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); | 445 | std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File)); |
| 443 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); | 446 | memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); |
| 444 | WriteBackupData(encrypted_tag_data.uuid, data); | 447 | WriteBackupData(encrypted_tag_data.uuid, data); |
| 445 | } | 448 | } |
| 446 | 449 | ||
| 447 | device_state = DeviceState::TagMounted; | 450 | if (is_corrupted && mount_target != NFP::MountTarget::Rom) { |
| 448 | mount_target = mount_target_; | ||
| 449 | |||
| 450 | if (is_corrupted) { | ||
| 451 | bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); | 451 | bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess(); |
| 452 | return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; | 452 | return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData; |
| 453 | } | 453 | } |
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index 4feb6968a..814407535 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp | |||
| @@ -74,10 +74,8 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::KProcess& process, Core::S | |||
| 74 | return load_result; | 74 | return load_result; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) { | 77 | system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>( |
| 78 | system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>( | 78 | *this, system.GetContentProvider(), system.GetFileSystemController())); |
| 79 | *this, system.GetContentProvider(), system.GetFileSystemController())); | ||
| 80 | } | ||
| 81 | 79 | ||
| 82 | is_loaded = true; | 80 | is_loaded = true; |
| 83 | return load_result; | 81 | return load_result; |
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp index fd9a99449..b2ceeefc4 100644 --- a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/div_ceil.h" | ||
| 4 | #include "shader_recompiler/backend/bindings.h" | 5 | #include "shader_recompiler/backend/bindings.h" |
| 5 | #include "shader_recompiler/backend/glsl/glsl_emit_context.h" | 6 | #include "shader_recompiler/backend/glsl/glsl_emit_context.h" |
| 6 | #include "shader_recompiler/frontend/ir/program.h" | 7 | #include "shader_recompiler/frontend/ir/program.h" |
| @@ -431,9 +432,11 @@ void EmitContext::DefineConstantBuffers(Bindings& bindings) { | |||
| 431 | } | 432 | } |
| 432 | for (const auto& desc : info.constant_buffer_descriptors) { | 433 | for (const auto& desc : info.constant_buffer_descriptors) { |
| 433 | const auto cbuf_type{profile.has_gl_cbuf_ftou_bug ? "uvec4" : "vec4"}; | 434 | const auto cbuf_type{profile.has_gl_cbuf_ftou_bug ? "uvec4" : "vec4"}; |
| 435 | const u32 cbuf_used_size{Common::DivCeil(info.constant_buffer_used_sizes[desc.index], 16U)}; | ||
| 436 | const u32 cbuf_binding_size{info.uses_global_memory ? 0x1000U : cbuf_used_size}; | ||
| 434 | header += fmt::format("layout(std140,binding={}) uniform {}_cbuf_{}{{{} {}_cbuf{}[{}];}};", | 437 | header += fmt::format("layout(std140,binding={}) uniform {}_cbuf_{}{{{} {}_cbuf{}[{}];}};", |
| 435 | bindings.uniform_buffer, stage_name, desc.index, cbuf_type, | 438 | bindings.uniform_buffer, stage_name, desc.index, cbuf_type, |
| 436 | stage_name, desc.index, 4 * 1024); | 439 | stage_name, desc.index, cbuf_binding_size); |
| 437 | bindings.uniform_buffer += desc.count; | 440 | bindings.uniform_buffer += desc.count; |
| 438 | } | 441 | } |
| 439 | } | 442 | } |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index dfd696de6..e6c70fb34 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -53,13 +53,11 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rast | |||
| 53 | VAddr cpu_addr_, u64 size_bytes_) | 53 | VAddr cpu_addr_, u64 size_bytes_) |
| 54 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) { | 54 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) { |
| 55 | buffer.Create(); | 55 | buffer.Create(); |
| 56 | const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); | 56 | if (runtime.device.HasDebuggingToolAttached()) { |
| 57 | glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data()); | 57 | const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); |
| 58 | glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW); | 58 | glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data()); |
| 59 | |||
| 60 | if (runtime.has_unified_vertex_buffers) { | ||
| 61 | glGetNamedBufferParameterui64vNV(buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &address); | ||
| 62 | } | 59 | } |
| 60 | glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW); | ||
| 63 | } | 61 | } |
| 64 | 62 | ||
| 65 | void Buffer::ImmediateUpload(size_t offset, std::span<const u8> data) noexcept { | 63 | void Buffer::ImmediateUpload(size_t offset, std::span<const u8> data) noexcept { |
| @@ -111,7 +109,6 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, | |||
| 111 | : device{device_}, staging_buffer_pool{staging_buffer_pool_}, | 109 | : device{device_}, staging_buffer_pool{staging_buffer_pool_}, |
| 112 | has_fast_buffer_sub_data{device.HasFastBufferSubData()}, | 110 | has_fast_buffer_sub_data{device.HasFastBufferSubData()}, |
| 113 | use_assembly_shaders{device.UseAssemblyShaders()}, | 111 | use_assembly_shaders{device.UseAssemblyShaders()}, |
| 114 | has_unified_vertex_buffers{device.HasVertexBufferUnifiedMemory()}, | ||
| 115 | stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} { | 112 | stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} { |
| 116 | GLint gl_max_attributes; | 113 | GLint gl_max_attributes; |
| 117 | glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes); | 114 | glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes); |
| @@ -123,16 +120,18 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, | |||
| 123 | GL_STREAM_DRAW); | 120 | GL_STREAM_DRAW); |
| 124 | } | 121 | } |
| 125 | } | 122 | } |
| 126 | for (auto& stage_uniforms : copy_uniforms) { | 123 | if (use_assembly_shaders) { |
| 127 | for (OGLBuffer& buffer : stage_uniforms) { | 124 | for (auto& stage_uniforms : copy_uniforms) { |
| 125 | for (OGLBuffer& buffer : stage_uniforms) { | ||
| 126 | buffer.Create(); | ||
| 127 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | for (OGLBuffer& buffer : copy_compute_uniforms) { | ||
| 128 | buffer.Create(); | 131 | buffer.Create(); |
| 129 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); | 132 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); |
| 130 | } | 133 | } |
| 131 | } | 134 | } |
| 132 | for (OGLBuffer& buffer : copy_compute_uniforms) { | ||
| 133 | buffer.Create(); | ||
| 134 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); | ||
| 135 | } | ||
| 136 | 135 | ||
| 137 | device_access_memory = [this]() -> u64 { | 136 | device_access_memory = [this]() -> u64 { |
| 138 | if (device.CanReportMemoryUsage()) { | 137 | if (device.CanReportMemoryUsage()) { |
| @@ -146,8 +145,12 @@ StagingBufferMap BufferCacheRuntime::UploadStagingBuffer(size_t size) { | |||
| 146 | return staging_buffer_pool.RequestUploadBuffer(size); | 145 | return staging_buffer_pool.RequestUploadBuffer(size); |
| 147 | } | 146 | } |
| 148 | 147 | ||
| 149 | StagingBufferMap BufferCacheRuntime::DownloadStagingBuffer(size_t size) { | 148 | StagingBufferMap BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { |
| 150 | return staging_buffer_pool.RequestDownloadBuffer(size); | 149 | return staging_buffer_pool.RequestDownloadBuffer(size, deferred); |
| 150 | } | ||
| 151 | |||
| 152 | void BufferCacheRuntime::FreeDeferredStagingBuffer(StagingBufferMap& buffer) { | ||
| 153 | staging_buffer_pool.FreeDeferredStagingBuffer(buffer); | ||
| 151 | } | 154 | } |
| 152 | 155 | ||
| 153 | u64 BufferCacheRuntime::GetDeviceMemoryUsage() const { | 156 | u64 BufferCacheRuntime::GetDeviceMemoryUsage() const { |
| @@ -207,14 +210,8 @@ void BufferCacheRuntime::ClearBuffer(Buffer& dest_buffer, u32 offset, size_t siz | |||
| 207 | } | 210 | } |
| 208 | 211 | ||
| 209 | void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) { | 212 | void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) { |
| 210 | if (has_unified_vertex_buffers) { | 213 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.Handle()); |
| 211 | buffer.MakeResident(GL_READ_ONLY); | 214 | index_buffer_offset = offset; |
| 212 | glBufferAddressRangeNV(GL_ELEMENT_ARRAY_ADDRESS_NV, 0, buffer.HostGpuAddr() + offset, | ||
| 213 | static_cast<GLsizeiptr>(Common::AlignUp(size, 4))); | ||
| 214 | } else { | ||
| 215 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.Handle()); | ||
| 216 | index_buffer_offset = offset; | ||
| 217 | } | ||
| 218 | } | 215 | } |
| 219 | 216 | ||
| 220 | void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, | 217 | void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, |
| @@ -222,24 +219,23 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, | |||
| 222 | if (index >= max_attributes) { | 219 | if (index >= max_attributes) { |
| 223 | return; | 220 | return; |
| 224 | } | 221 | } |
| 225 | if (has_unified_vertex_buffers) { | 222 | glBindVertexBuffer(index, buffer.Handle(), static_cast<GLintptr>(offset), |
| 226 | buffer.MakeResident(GL_READ_ONLY); | 223 | static_cast<GLsizei>(stride)); |
| 227 | glBindVertexBuffer(index, 0, 0, static_cast<GLsizei>(stride)); | ||
| 228 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, index, | ||
| 229 | buffer.HostGpuAddr() + offset, static_cast<GLsizeiptr>(size)); | ||
| 230 | } else { | ||
| 231 | glBindVertexBuffer(index, buffer.Handle(), static_cast<GLintptr>(offset), | ||
| 232 | static_cast<GLsizei>(stride)); | ||
| 233 | } | ||
| 234 | } | 224 | } |
| 235 | 225 | ||
| 236 | void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) { | 226 | void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) { |
| 237 | for (u32 index = 0; index < bindings.buffers.size(); ++index) { | 227 | // TODO: Should HostBindings provide the correct runtime types to avoid these transforms? |
| 238 | BindVertexBuffer(bindings.min_index + index, *bindings.buffers[index], | 228 | std::array<GLuint, 32> buffer_handles; |
| 239 | static_cast<u32>(bindings.offsets[index]), | 229 | std::array<GLsizei, 32> buffer_strides; |
| 240 | static_cast<u32>(bindings.sizes[index]), | 230 | std::ranges::transform(bindings.buffers, buffer_handles.begin(), |
| 241 | static_cast<u32>(bindings.strides[index])); | 231 | [](const Buffer* const buffer) { return buffer->Handle(); }); |
| 242 | } | 232 | std::ranges::transform(bindings.strides, buffer_strides.begin(), |
| 233 | [](u64 stride) { return static_cast<GLsizei>(stride); }); | ||
| 234 | const u32 count = | ||
| 235 | std::min(static_cast<u32>(bindings.buffers.size()), max_attributes - bindings.min_index); | ||
| 236 | glBindVertexBuffers(bindings.min_index, static_cast<GLsizei>(count), buffer_handles.data(), | ||
| 237 | reinterpret_cast<const GLintptr*>(bindings.offsets.data()), | ||
| 238 | buffer_strides.data()); | ||
| 243 | } | 239 | } |
| 244 | 240 | ||
| 245 | void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, | 241 | void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, |
| @@ -331,11 +327,13 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, Buffer& buffer, | |||
| 331 | } | 327 | } |
| 332 | 328 | ||
| 333 | void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings) { | 329 | void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings) { |
| 334 | for (u32 index = 0; index < bindings.buffers.size(); ++index) { | 330 | std::array<GLuint, 4> buffer_handles; |
| 335 | glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index, bindings.buffers[index]->Handle(), | 331 | std::ranges::transform(bindings.buffers, buffer_handles.begin(), |
| 336 | static_cast<GLintptr>(bindings.offsets[index]), | 332 | [](const Buffer* const buffer) { return buffer->Handle(); }); |
| 337 | static_cast<GLsizeiptr>(bindings.sizes[index])); | 333 | glBindBuffersRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, |
| 338 | } | 334 | static_cast<GLsizei>(bindings.buffers.size()), buffer_handles.data(), |
| 335 | reinterpret_cast<const GLintptr*>(bindings.offsets.data()), | ||
| 336 | reinterpret_cast<const GLsizeiptr*>(bindings.strides.data())); | ||
| 339 | } | 337 | } |
| 340 | 338 | ||
| 341 | void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, | 339 | void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 000f29a82..71cd45d35 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -66,7 +66,9 @@ public: | |||
| 66 | 66 | ||
| 67 | [[nodiscard]] StagingBufferMap UploadStagingBuffer(size_t size); | 67 | [[nodiscard]] StagingBufferMap UploadStagingBuffer(size_t size); |
| 68 | 68 | ||
| 69 | [[nodiscard]] StagingBufferMap DownloadStagingBuffer(size_t size); | 69 | [[nodiscard]] StagingBufferMap DownloadStagingBuffer(size_t size, bool deferred = false); |
| 70 | |||
| 71 | void FreeDeferredStagingBuffer(StagingBufferMap& buffer); | ||
| 70 | 72 | ||
| 71 | bool CanReorderUpload(const Buffer&, std::span<const VideoCommon::BufferCopy>) { | 73 | bool CanReorderUpload(const Buffer&, std::span<const VideoCommon::BufferCopy>) { |
| 72 | return false; | 74 | return false; |
| @@ -207,7 +209,6 @@ private: | |||
| 207 | 209 | ||
| 208 | bool has_fast_buffer_sub_data = false; | 210 | bool has_fast_buffer_sub_data = false; |
| 209 | bool use_assembly_shaders = false; | 211 | bool use_assembly_shaders = false; |
| 210 | bool has_unified_vertex_buffers = false; | ||
| 211 | 212 | ||
| 212 | bool use_storage_buffers = false; | 213 | bool use_storage_buffers = false; |
| 213 | 214 | ||
| @@ -246,7 +247,7 @@ struct BufferCacheParams { | |||
| 246 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = true; | 247 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = true; |
| 247 | static constexpr bool USE_MEMORY_MAPS = true; | 248 | static constexpr bool USE_MEMORY_MAPS = true; |
| 248 | static constexpr bool SEPARATE_IMAGE_BUFFER_BINDINGS = true; | 249 | static constexpr bool SEPARATE_IMAGE_BUFFER_BINDINGS = true; |
| 249 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = false; | 250 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true; |
| 250 | 251 | ||
| 251 | // TODO: Investigate why OpenGL seems to perform worse with persistently mapped buffer uploads | 252 | // TODO: Investigate why OpenGL seems to perform worse with persistently mapped buffer uploads |
| 252 | static constexpr bool USE_MEMORY_MAPS_FOR_UPLOADS = false; | 253 | static constexpr bool USE_MEMORY_MAPS_FOR_UPLOADS = false; |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 993438a27..a6c93068f 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -200,7 +200,6 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) { | |||
| 200 | has_broken_texture_view_formats = is_amd || (!is_linux && is_intel); | 200 | has_broken_texture_view_formats = is_amd || (!is_linux && is_intel); |
| 201 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; | 201 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; |
| 202 | has_derivative_control = GLAD_GL_ARB_derivative_control; | 202 | has_derivative_control = GLAD_GL_ARB_derivative_control; |
| 203 | has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory; | ||
| 204 | has_debugging_tool_attached = IsDebugToolAttached(extensions); | 203 | has_debugging_tool_attached = IsDebugToolAttached(extensions); |
| 205 | has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float"); | 204 | has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float"); |
| 206 | has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough; | 205 | has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough; |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index a5a6bbbba..96034ea4a 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -72,10 +72,6 @@ public: | |||
| 72 | return has_texture_shadow_lod; | 72 | return has_texture_shadow_lod; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | bool HasVertexBufferUnifiedMemory() const { | ||
| 76 | return has_vertex_buffer_unified_memory; | ||
| 77 | } | ||
| 78 | |||
| 79 | bool HasASTC() const { | 75 | bool HasASTC() const { |
| 80 | return has_astc; | 76 | return has_astc; |
| 81 | } | 77 | } |
| @@ -215,7 +211,6 @@ private: | |||
| 215 | bool has_vertex_viewport_layer{}; | 211 | bool has_vertex_viewport_layer{}; |
| 216 | bool has_image_load_formatted{}; | 212 | bool has_image_load_formatted{}; |
| 217 | bool has_texture_shadow_lod{}; | 213 | bool has_texture_shadow_lod{}; |
| 218 | bool has_vertex_buffer_unified_memory{}; | ||
| 219 | bool has_astc{}; | 214 | bool has_astc{}; |
| 220 | bool has_variable_aoffi{}; | 215 | bool has_variable_aoffi{}; |
| 221 | bool has_component_indexing_bug{}; | 216 | bool has_component_indexing_bug{}; |
diff --git a/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp b/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp index bbb06e51f..cadad6507 100644 --- a/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp +++ b/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp | |||
| @@ -28,63 +28,69 @@ StagingBuffers::StagingBuffers(GLenum storage_flags_, GLenum map_flags_) | |||
| 28 | 28 | ||
| 29 | StagingBuffers::~StagingBuffers() = default; | 29 | StagingBuffers::~StagingBuffers() = default; |
| 30 | 30 | ||
| 31 | StagingBufferMap StagingBuffers::RequestMap(size_t requested_size, bool insert_fence) { | 31 | StagingBufferMap StagingBuffers::RequestMap(size_t requested_size, bool insert_fence, |
| 32 | bool deferred) { | ||
| 32 | MICROPROFILE_SCOPE(OpenGL_BufferRequest); | 33 | MICROPROFILE_SCOPE(OpenGL_BufferRequest); |
| 33 | 34 | ||
| 34 | const size_t index = RequestBuffer(requested_size); | 35 | const size_t index = RequestBuffer(requested_size); |
| 35 | OGLSync* const sync = insert_fence ? &syncs[index] : nullptr; | 36 | OGLSync* const sync = insert_fence ? &allocs[index].sync : nullptr; |
| 36 | sync_indices[index] = insert_fence ? ++current_sync_index : 0; | 37 | allocs[index].sync_index = insert_fence ? ++current_sync_index : 0; |
| 38 | allocs[index].deferred = deferred; | ||
| 37 | return StagingBufferMap{ | 39 | return StagingBufferMap{ |
| 38 | .mapped_span = std::span(maps[index], requested_size), | 40 | .mapped_span = std::span(allocs[index].map, requested_size), |
| 39 | .sync = sync, | 41 | .sync = sync, |
| 40 | .buffer = buffers[index].handle, | 42 | .buffer = allocs[index].buffer.handle, |
| 43 | .index = index, | ||
| 41 | }; | 44 | }; |
| 42 | } | 45 | } |
| 43 | 46 | ||
| 47 | void StagingBuffers::FreeDeferredStagingBuffer(size_t index) { | ||
| 48 | ASSERT(allocs[index].deferred); | ||
| 49 | allocs[index].deferred = false; | ||
| 50 | } | ||
| 51 | |||
| 44 | size_t StagingBuffers::RequestBuffer(size_t requested_size) { | 52 | size_t StagingBuffers::RequestBuffer(size_t requested_size) { |
| 45 | if (const std::optional<size_t> index = FindBuffer(requested_size); index) { | 53 | if (const std::optional<size_t> index = FindBuffer(requested_size); index) { |
| 46 | return *index; | 54 | return *index; |
| 47 | } | 55 | } |
| 48 | 56 | StagingBufferAlloc alloc; | |
| 49 | OGLBuffer& buffer = buffers.emplace_back(); | 57 | alloc.buffer.Create(); |
| 50 | buffer.Create(); | ||
| 51 | const auto next_pow2_size = Common::NextPow2(requested_size); | 58 | const auto next_pow2_size = Common::NextPow2(requested_size); |
| 52 | glNamedBufferStorage(buffer.handle, next_pow2_size, nullptr, | 59 | glNamedBufferStorage(alloc.buffer.handle, next_pow2_size, nullptr, |
| 53 | storage_flags | GL_MAP_PERSISTENT_BIT); | 60 | storage_flags | GL_MAP_PERSISTENT_BIT); |
| 54 | maps.push_back(static_cast<u8*>(glMapNamedBufferRange(buffer.handle, 0, next_pow2_size, | 61 | alloc.map = static_cast<u8*>(glMapNamedBufferRange(alloc.buffer.handle, 0, next_pow2_size, |
| 55 | map_flags | GL_MAP_PERSISTENT_BIT))); | 62 | map_flags | GL_MAP_PERSISTENT_BIT)); |
| 56 | syncs.emplace_back(); | 63 | alloc.size = next_pow2_size; |
| 57 | sync_indices.emplace_back(); | 64 | allocs.emplace_back(std::move(alloc)); |
| 58 | sizes.push_back(next_pow2_size); | 65 | return allocs.size() - 1; |
| 59 | |||
| 60 | ASSERT(syncs.size() == buffers.size() && buffers.size() == maps.size() && | ||
| 61 | maps.size() == sizes.size()); | ||
| 62 | |||
| 63 | return buffers.size() - 1; | ||
| 64 | } | 66 | } |
| 65 | 67 | ||
| 66 | std::optional<size_t> StagingBuffers::FindBuffer(size_t requested_size) { | 68 | std::optional<size_t> StagingBuffers::FindBuffer(size_t requested_size) { |
| 67 | size_t known_unsignaled_index = current_sync_index + 1; | 69 | size_t known_unsignaled_index = current_sync_index + 1; |
| 68 | size_t smallest_buffer = std::numeric_limits<size_t>::max(); | 70 | size_t smallest_buffer = std::numeric_limits<size_t>::max(); |
| 69 | std::optional<size_t> found; | 71 | std::optional<size_t> found; |
| 70 | const size_t num_buffers = sizes.size(); | 72 | const size_t num_buffers = allocs.size(); |
| 71 | for (size_t index = 0; index < num_buffers; ++index) { | 73 | for (size_t index = 0; index < num_buffers; ++index) { |
| 72 | const size_t buffer_size = sizes[index]; | 74 | StagingBufferAlloc& alloc = allocs[index]; |
| 75 | const size_t buffer_size = alloc.size; | ||
| 73 | if (buffer_size < requested_size || buffer_size >= smallest_buffer) { | 76 | if (buffer_size < requested_size || buffer_size >= smallest_buffer) { |
| 74 | continue; | 77 | continue; |
| 75 | } | 78 | } |
| 76 | if (syncs[index].handle != 0) { | 79 | if (alloc.deferred) { |
| 77 | if (sync_indices[index] >= known_unsignaled_index) { | 80 | continue; |
| 81 | } | ||
| 82 | if (alloc.sync.handle != 0) { | ||
| 83 | if (alloc.sync_index >= known_unsignaled_index) { | ||
| 78 | // This fence is later than a fence that is known to not be signaled | 84 | // This fence is later than a fence that is known to not be signaled |
| 79 | continue; | 85 | continue; |
| 80 | } | 86 | } |
| 81 | if (!syncs[index].IsSignaled()) { | 87 | if (!alloc.sync.IsSignaled()) { |
| 82 | // Since this fence hasn't been signaled, it's safe to assume all later | 88 | // Since this fence hasn't been signaled, it's safe to assume all later |
| 83 | // fences haven't been signaled either | 89 | // fences haven't been signaled either |
| 84 | known_unsignaled_index = std::min(known_unsignaled_index, sync_indices[index]); | 90 | known_unsignaled_index = std::min(known_unsignaled_index, alloc.sync_index); |
| 85 | continue; | 91 | continue; |
| 86 | } | 92 | } |
| 87 | syncs[index].Release(); | 93 | alloc.sync.Release(); |
| 88 | } | 94 | } |
| 89 | smallest_buffer = buffer_size; | 95 | smallest_buffer = buffer_size; |
| 90 | found = index; | 96 | found = index; |
| @@ -143,8 +149,12 @@ StagingBufferMap StagingBufferPool::RequestUploadBuffer(size_t size) { | |||
| 143 | return upload_buffers.RequestMap(size, true); | 149 | return upload_buffers.RequestMap(size, true); |
| 144 | } | 150 | } |
| 145 | 151 | ||
| 146 | StagingBufferMap StagingBufferPool::RequestDownloadBuffer(size_t size) { | 152 | StagingBufferMap StagingBufferPool::RequestDownloadBuffer(size_t size, bool deferred) { |
| 147 | return download_buffers.RequestMap(size, false); | 153 | return download_buffers.RequestMap(size, false, deferred); |
| 154 | } | ||
| 155 | |||
| 156 | void StagingBufferPool::FreeDeferredStagingBuffer(StagingBufferMap& buffer) { | ||
| 157 | download_buffers.FreeDeferredStagingBuffer(buffer.index); | ||
| 148 | } | 158 | } |
| 149 | 159 | ||
| 150 | } // namespace OpenGL | 160 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_staging_buffer_pool.h b/src/video_core/renderer_opengl/gl_staging_buffer_pool.h index 60f72d3a0..07a56b4d2 100644 --- a/src/video_core/renderer_opengl/gl_staging_buffer_pool.h +++ b/src/video_core/renderer_opengl/gl_staging_buffer_pool.h | |||
| @@ -26,23 +26,30 @@ struct StagingBufferMap { | |||
| 26 | size_t offset = 0; | 26 | size_t offset = 0; |
| 27 | OGLSync* sync; | 27 | OGLSync* sync; |
| 28 | GLuint buffer; | 28 | GLuint buffer; |
| 29 | size_t index; | ||
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 31 | struct StagingBuffers { | 32 | struct StagingBuffers { |
| 32 | explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_); | 33 | explicit StagingBuffers(GLenum storage_flags_, GLenum map_flags_); |
| 33 | ~StagingBuffers(); | 34 | ~StagingBuffers(); |
| 34 | 35 | ||
| 35 | StagingBufferMap RequestMap(size_t requested_size, bool insert_fence); | 36 | StagingBufferMap RequestMap(size_t requested_size, bool insert_fence, bool deferred = false); |
| 37 | |||
| 38 | void FreeDeferredStagingBuffer(size_t index); | ||
| 36 | 39 | ||
| 37 | size_t RequestBuffer(size_t requested_size); | 40 | size_t RequestBuffer(size_t requested_size); |
| 38 | 41 | ||
| 39 | std::optional<size_t> FindBuffer(size_t requested_size); | 42 | std::optional<size_t> FindBuffer(size_t requested_size); |
| 40 | 43 | ||
| 41 | std::vector<OGLSync> syncs; | 44 | struct StagingBufferAlloc { |
| 42 | std::vector<OGLBuffer> buffers; | 45 | OGLSync sync; |
| 43 | std::vector<u8*> maps; | 46 | OGLBuffer buffer; |
| 44 | std::vector<size_t> sizes; | 47 | u8* map; |
| 45 | std::vector<size_t> sync_indices; | 48 | size_t size; |
| 49 | size_t sync_index; | ||
| 50 | bool deferred; | ||
| 51 | }; | ||
| 52 | std::vector<StagingBufferAlloc> allocs; | ||
| 46 | GLenum storage_flags; | 53 | GLenum storage_flags; |
| 47 | GLenum map_flags; | 54 | GLenum map_flags; |
| 48 | size_t current_sync_index = 0; | 55 | size_t current_sync_index = 0; |
| @@ -85,7 +92,8 @@ public: | |||
| 85 | ~StagingBufferPool() = default; | 92 | ~StagingBufferPool() = default; |
| 86 | 93 | ||
| 87 | StagingBufferMap RequestUploadBuffer(size_t size); | 94 | StagingBufferMap RequestUploadBuffer(size_t size); |
| 88 | StagingBufferMap RequestDownloadBuffer(size_t size); | 95 | StagingBufferMap RequestDownloadBuffer(size_t size, bool deferred = false); |
| 96 | void FreeDeferredStagingBuffer(StagingBufferMap& buffer); | ||
| 89 | 97 | ||
| 90 | private: | 98 | private: |
| 91 | StagingBuffers upload_buffers{GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT}; | 99 | StagingBuffers upload_buffers{GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT}; |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 512eef575..66a5ca03e 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -557,8 +557,12 @@ StagingBufferMap TextureCacheRuntime::UploadStagingBuffer(size_t size) { | |||
| 557 | return staging_buffer_pool.RequestUploadBuffer(size); | 557 | return staging_buffer_pool.RequestUploadBuffer(size); |
| 558 | } | 558 | } |
| 559 | 559 | ||
| 560 | StagingBufferMap TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | 560 | StagingBufferMap TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { |
| 561 | return staging_buffer_pool.RequestDownloadBuffer(size); | 561 | return staging_buffer_pool.RequestDownloadBuffer(size, deferred); |
| 562 | } | ||
| 563 | |||
| 564 | void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferMap& buffer) { | ||
| 565 | staging_buffer_pool.FreeDeferredStagingBuffer(buffer); | ||
| 562 | } | 566 | } |
| 563 | 567 | ||
| 564 | u64 TextureCacheRuntime::GetDeviceMemoryUsage() const { | 568 | u64 TextureCacheRuntime::GetDeviceMemoryUsage() const { |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index e71b87e99..34870c81f 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -74,7 +74,9 @@ public: | |||
| 74 | 74 | ||
| 75 | StagingBufferMap UploadStagingBuffer(size_t size); | 75 | StagingBufferMap UploadStagingBuffer(size_t size); |
| 76 | 76 | ||
| 77 | StagingBufferMap DownloadStagingBuffer(size_t size); | 77 | StagingBufferMap DownloadStagingBuffer(size_t size, bool deferred = false); |
| 78 | |||
| 79 | void FreeDeferredStagingBuffer(StagingBufferMap& buffer); | ||
| 78 | 80 | ||
| 79 | u64 GetDeviceLocalMemory() const { | 81 | u64 GetDeviceLocalMemory() const { |
| 80 | return device_access_memory; | 82 | return device_access_memory; |
| @@ -359,7 +361,7 @@ struct TextureCacheParams { | |||
| 359 | static constexpr bool FRAMEBUFFER_BLITS = true; | 361 | static constexpr bool FRAMEBUFFER_BLITS = true; |
| 360 | static constexpr bool HAS_EMULATED_COPIES = true; | 362 | static constexpr bool HAS_EMULATED_COPIES = true; |
| 361 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; | 363 | static constexpr bool HAS_DEVICE_MEMORY_INFO = true; |
| 362 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = false; | 364 | static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true; |
| 363 | 365 | ||
| 364 | using Runtime = OpenGL::TextureCacheRuntime; | 366 | using Runtime = OpenGL::TextureCacheRuntime; |
| 365 | using Image = OpenGL::Image; | 367 | using Image = OpenGL::Image; |
| @@ -367,7 +369,7 @@ struct TextureCacheParams { | |||
| 367 | using ImageView = OpenGL::ImageView; | 369 | using ImageView = OpenGL::ImageView; |
| 368 | using Sampler = OpenGL::Sampler; | 370 | using Sampler = OpenGL::Sampler; |
| 369 | using Framebuffer = OpenGL::Framebuffer; | 371 | using Framebuffer = OpenGL::Framebuffer; |
| 370 | using AsyncBuffer = u32; | 372 | using AsyncBuffer = OpenGL::StagingBufferMap; |
| 371 | using BufferType = GLuint; | 373 | using BufferType = GLuint; |
| 372 | }; | 374 | }; |
| 373 | 375 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 6b8d4e554..6bfed08a1 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -168,15 +168,6 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, | |||
| 168 | if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) { | 168 | if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) { |
| 169 | glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); | 169 | glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); |
| 170 | } | 170 | } |
| 171 | // Enable unified vertex attributes and query vertex buffer address when the driver supports it | ||
| 172 | if (device.HasVertexBufferUnifiedMemory()) { | ||
| 173 | glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); | ||
| 174 | glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV); | ||
| 175 | |||
| 176 | glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY); | ||
| 177 | glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, | ||
| 178 | &vertex_buffer_address); | ||
| 179 | } | ||
| 180 | } | 171 | } |
| 181 | 172 | ||
| 182 | RendererOpenGL::~RendererOpenGL() = default; | 173 | RendererOpenGL::~RendererOpenGL() = default; |
| @@ -680,13 +671,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 680 | offsetof(ScreenRectVertex, tex_coord)); | 671 | offsetof(ScreenRectVertex, tex_coord)); |
| 681 | glVertexAttribBinding(PositionLocation, 0); | 672 | glVertexAttribBinding(PositionLocation, 0); |
| 682 | glVertexAttribBinding(TexCoordLocation, 0); | 673 | glVertexAttribBinding(TexCoordLocation, 0); |
| 683 | if (device.HasVertexBufferUnifiedMemory()) { | 674 | glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); |
| 684 | glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex)); | ||
| 685 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address, | ||
| 686 | sizeof(vertices)); | ||
| 687 | } else { | ||
| 688 | glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); | ||
| 689 | } | ||
| 690 | 675 | ||
| 691 | if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) { | 676 | if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) { |
| 692 | glBindSampler(0, present_sampler.handle); | 677 | glBindSampler(0, present_sampler.handle); |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 66483a900..5e461fbd0 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -1211,7 +1211,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { | |||
| 1211 | aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); | 1211 | aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); |
| 1212 | return; | 1212 | return; |
| 1213 | } | 1213 | } |
| 1214 | aa_renderpass = CreateRenderPassImpl(GetFormat(framebuffer)); | 1214 | aa_renderpass = CreateRenderPassImpl(VK_FORMAT_R16G16B16A16_SFLOAT); |
| 1215 | aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); | 1215 | aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); |
| 1216 | 1216 | ||
| 1217 | const std::array<VkPipelineShaderStageCreateInfo, 2> fxaa_shader_stages{{ | 1217 | const std::array<VkPipelineShaderStageCreateInfo, 2> fxaa_shader_stages{{ |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 5dbec2e62..38b1619df 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -1439,7 +1439,7 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag | |||
| 1439 | UploadMemory(map.buffer, map.offset, copies); | 1439 | UploadMemory(map.buffer, map.offset, copies); |
| 1440 | } | 1440 | } |
| 1441 | 1441 | ||
| 1442 | void Image::DownloadMemory(VkBuffer buffer, VkDeviceSize offset, | 1442 | void Image::DownloadMemory(VkBuffer buffer, size_t offset, |
| 1443 | std::span<const VideoCommon::BufferImageCopy> copies) { | 1443 | std::span<const VideoCommon::BufferImageCopy> copies) { |
| 1444 | std::array buffer_handles{ | 1444 | std::array buffer_handles{ |
| 1445 | buffer, | 1445 | buffer, |
| @@ -1450,7 +1450,7 @@ void Image::DownloadMemory(VkBuffer buffer, VkDeviceSize offset, | |||
| 1450 | DownloadMemory(buffer_handles, buffer_offsets, copies); | 1450 | DownloadMemory(buffer_handles, buffer_offsets, copies); |
| 1451 | } | 1451 | } |
| 1452 | 1452 | ||
| 1453 | void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceSize> offsets_span, | 1453 | void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> offsets_span, |
| 1454 | std::span<const VideoCommon::BufferImageCopy> copies) { | 1454 | std::span<const VideoCommon::BufferImageCopy> copies) { |
| 1455 | const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); | 1455 | const bool is_rescaled = True(flags & ImageFlagBits::Rescaled); |
| 1456 | if (is_rescaled) { | 1456 | if (is_rescaled) { |
| @@ -1530,7 +1530,7 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm | |||
| 1530 | map.buffer, | 1530 | map.buffer, |
| 1531 | }; | 1531 | }; |
| 1532 | std::array offsets{ | 1532 | std::array offsets{ |
| 1533 | map.offset, | 1533 | static_cast<size_t>(map.offset), |
| 1534 | }; | 1534 | }; |
| 1535 | DownloadMemory(buffers, offsets, copies); | 1535 | DownloadMemory(buffers, offsets, copies); |
| 1536 | } | 1536 | } |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index edf5d7635..0dbde65d6 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -147,10 +147,10 @@ public: | |||
| 147 | void UploadMemory(const StagingBufferRef& map, | 147 | void UploadMemory(const StagingBufferRef& map, |
| 148 | std::span<const VideoCommon::BufferImageCopy> copies); | 148 | std::span<const VideoCommon::BufferImageCopy> copies); |
| 149 | 149 | ||
| 150 | void DownloadMemory(VkBuffer buffer, VkDeviceSize offset, | 150 | void DownloadMemory(VkBuffer buffer, size_t offset, |
| 151 | std::span<const VideoCommon::BufferImageCopy> copies); | 151 | std::span<const VideoCommon::BufferImageCopy> copies); |
| 152 | 152 | ||
| 153 | void DownloadMemory(std::span<VkBuffer> buffers, std::span<VkDeviceSize> offsets, | 153 | void DownloadMemory(std::span<VkBuffer> buffers, std::span<size_t> offsets, |
| 154 | std::span<const VideoCommon::BufferImageCopy> copies); | 154 | std::span<const VideoCommon::BufferImageCopy> copies); |
| 155 | 155 | ||
| 156 | void DownloadMemory(const StagingBufferRef& map, | 156 | void DownloadMemory(const StagingBufferRef& map, |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index d575c57ca..dade38b18 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -995,7 +995,7 @@ void TextureCache<P>::DownloadImageIntoBuffer(typename TextureCache<P>::Image* i | |||
| 995 | buffer, | 995 | buffer, |
| 996 | download_map.buffer, | 996 | download_map.buffer, |
| 997 | }; | 997 | }; |
| 998 | std::array<u64, 2> buffer_offsets{ | 998 | std::array<size_t, 2> buffer_offsets{ |
| 999 | buffer_offset, | 999 | buffer_offset, |
| 1000 | download_map.offset, | 1000 | download_map.offset, |
| 1001 | }; | 1001 | }; |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f3ad2214b..90278052a 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -386,7 +386,7 @@ if (NOT WIN32) | |||
| 386 | target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) | 386 | target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) |
| 387 | endif() | 387 | endif() |
| 388 | if (UNIX AND NOT APPLE) | 388 | if (UNIX AND NOT APPLE) |
| 389 | target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::DBus gamemode) | 389 | target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::DBus) |
| 390 | endif() | 390 | endif() |
| 391 | 391 | ||
| 392 | target_compile_definitions(yuzu PRIVATE | 392 | target_compile_definitions(yuzu PRIVATE |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 10c788290..b056c3717 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2713,11 +2713,6 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 2713 | } | 2713 | } |
| 2714 | 2714 | ||
| 2715 | const auto base_romfs = base_nca->GetRomFS(); | 2715 | const auto base_romfs = base_nca->GetRomFS(); |
| 2716 | if (!base_romfs) { | ||
| 2717 | failed(); | ||
| 2718 | return; | ||
| 2719 | } | ||
| 2720 | |||
| 2721 | const auto dump_dir = | 2716 | const auto dump_dir = |
| 2722 | target == DumpRomFSTarget::Normal | 2717 | target == DumpRomFSTarget::Normal |
| 2723 | ? Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir) | 2718 | ? Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir) |