diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | src/common/logging/backend.cpp | 50 | ||||
| -rw-r--r-- | src/common/logging/backend.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 37 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.h | 3 | ||||
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 116 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.h | 87 | ||||
| -rw-r--r-- | src/web_service/verify_login.h | 2 | ||||
| -rw-r--r-- | src/web_service/web_backend.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu/compatdb.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 5 |
13 files changed, 269 insertions, 44 deletions
| @@ -7,7 +7,7 @@ yuzu is an experimental open-source emulator for the Nintendo Switch from the cr | |||
| 7 | 7 | ||
| 8 | It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes. | 8 | It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes. |
| 9 | 9 | ||
| 10 | yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success, but does not implement any of the necessary GPU features to render 3D graphics. | 10 | yuzu only emulates a subset of Switch hardware and therefore is generally only useful for running/debugging homebrew applications. At this time, yuzu cannot play any commercial games without major problems. yuzu can boot some games, to varying degrees of success. |
| 11 | 11 | ||
| 12 | yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included. | 12 | yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included. |
| 13 | 13 | ||
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index b369f199f..4462ff3fb 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -39,8 +39,10 @@ public: | |||
| 39 | Impl(Impl const&) = delete; | 39 | Impl(Impl const&) = delete; |
| 40 | const Impl& operator=(Impl const&) = delete; | 40 | const Impl& operator=(Impl const&) = delete; |
| 41 | 41 | ||
| 42 | void PushEntry(Entry e) { | 42 | void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, |
| 43 | message_queue.Push(std::move(e)); | 43 | const char* function, std::string message) { |
| 44 | message_queue.Push( | ||
| 45 | CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); | ||
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | void AddBackend(std::unique_ptr<Backend> backend) { | 48 | void AddBackend(std::unique_ptr<Backend> backend) { |
| @@ -108,11 +110,30 @@ private: | |||
| 108 | backend_thread.join(); | 110 | backend_thread.join(); |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 113 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | ||
| 114 | const char* function, std::string message) const { | ||
| 115 | using std::chrono::duration_cast; | ||
| 116 | using std::chrono::steady_clock; | ||
| 117 | |||
| 118 | Entry entry; | ||
| 119 | entry.timestamp = | ||
| 120 | duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||
| 121 | entry.log_class = log_class; | ||
| 122 | entry.log_level = log_level; | ||
| 123 | entry.filename = Common::TrimSourcePath(filename); | ||
| 124 | entry.line_num = line_nr; | ||
| 125 | entry.function = function; | ||
| 126 | entry.message = std::move(message); | ||
| 127 | |||
| 128 | return entry; | ||
| 129 | } | ||
| 130 | |||
| 111 | std::mutex writing_mutex; | 131 | std::mutex writing_mutex; |
| 112 | std::thread backend_thread; | 132 | std::thread backend_thread; |
| 113 | std::vector<std::unique_ptr<Backend>> backends; | 133 | std::vector<std::unique_ptr<Backend>> backends; |
| 114 | Common::MPSCQueue<Log::Entry> message_queue; | 134 | Common::MPSCQueue<Log::Entry> message_queue; |
| 115 | Filter filter; | 135 | Filter filter; |
| 136 | std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; | ||
| 116 | }; | 137 | }; |
| 117 | 138 | ||
| 118 | void ConsoleBackend::Write(const Entry& entry) { | 139 | void ConsoleBackend::Write(const Entry& entry) { |
| @@ -271,25 +292,6 @@ const char* GetLevelName(Level log_level) { | |||
| 271 | #undef LVL | 292 | #undef LVL |
| 272 | } | 293 | } |
| 273 | 294 | ||
| 274 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | ||
| 275 | const char* function, std::string message) { | ||
| 276 | using std::chrono::duration_cast; | ||
| 277 | using std::chrono::steady_clock; | ||
| 278 | |||
| 279 | static steady_clock::time_point time_origin = steady_clock::now(); | ||
| 280 | |||
| 281 | Entry entry; | ||
| 282 | entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||
| 283 | entry.log_class = log_class; | ||
| 284 | entry.log_level = log_level; | ||
| 285 | entry.filename = Common::TrimSourcePath(filename); | ||
| 286 | entry.line_num = line_nr; | ||
| 287 | entry.function = function; | ||
| 288 | entry.message = std::move(message); | ||
| 289 | |||
| 290 | return entry; | ||
| 291 | } | ||
| 292 | |||
| 293 | void SetGlobalFilter(const Filter& filter) { | 295 | void SetGlobalFilter(const Filter& filter) { |
| 294 | Impl::Instance().SetGlobalFilter(filter); | 296 | Impl::Instance().SetGlobalFilter(filter); |
| 295 | } | 297 | } |
| @@ -314,9 +316,7 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | |||
| 314 | if (!filter.CheckMessage(log_class, log_level)) | 316 | if (!filter.CheckMessage(log_class, log_level)) |
| 315 | return; | 317 | return; |
| 316 | 318 | ||
| 317 | Entry entry = | 319 | instance.PushEntry(log_class, log_level, filename, line_num, function, |
| 318 | CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); | 320 | fmt::vformat(format, args)); |
| 319 | |||
| 320 | instance.PushEntry(std::move(entry)); | ||
| 321 | } | 321 | } |
| 322 | } // namespace Log | 322 | } // namespace Log |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index a31ee6968..fca0267a1 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -135,10 +135,6 @@ const char* GetLogClassName(Class log_class); | |||
| 135 | */ | 135 | */ |
| 136 | const char* GetLevelName(Level log_level); | 136 | const char* GetLevelName(Level log_level); |
| 137 | 137 | ||
| 138 | /// Creates a log entry by formatting the given source location, and message. | ||
| 139 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | ||
| 140 | const char* function, std::string message); | ||
| 141 | |||
| 142 | /** | 138 | /** |
| 143 | * The global filter will prevent any messages from even being processed if they are filtered. Each | 139 | * The global filter will prevent any messages from even being processed if they are filtered. Each |
| 144 | * backend can have a filter, but if the level is lower than the global filter, the backend will | 140 | * backend can have a filter, but if the level is lower than the global filter, the backend will |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 49648394c..ea8f9d0bb 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -37,7 +37,7 @@ public: | |||
| 37 | {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, | 37 | {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, |
| 38 | {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, | 38 | {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, |
| 39 | {10, &IAudioRenderer::RequestUpdateImpl, "RequestUpdateAuto"}, | 39 | {10, &IAudioRenderer::RequestUpdateImpl, "RequestUpdateAuto"}, |
| 40 | {11, nullptr, "ExecuteAudioRendererRendering"}, | 40 | {11, &IAudioRenderer::ExecuteAudioRendererRendering, "ExecuteAudioRendererRendering"}, |
| 41 | }; | 41 | }; |
| 42 | // clang-format on | 42 | // clang-format on |
| 43 | RegisterHandlers(functions); | 43 | RegisterHandlers(functions); |
| @@ -138,6 +138,17 @@ private: | |||
| 138 | rb.Push(rendering_time_limit_percent); | 138 | rb.Push(rendering_time_limit_percent); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | void ExecuteAudioRendererRendering(Kernel::HLERequestContext& ctx) { | ||
| 142 | LOG_DEBUG(Service_Audio, "called"); | ||
| 143 | |||
| 144 | // This service command currently only reports an unsupported operation | ||
| 145 | // error code, or aborts. Given that, we just always return an error | ||
| 146 | // code in this case. | ||
| 147 | |||
| 148 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 149 | rb.Push(ResultCode{ErrorModule::Audio, 201}); | ||
| 150 | } | ||
| 151 | |||
| 141 | Kernel::EventPair system_event; | 152 | Kernel::EventPair system_event; |
| 142 | std::unique_ptr<AudioCore::AudioRenderer> renderer; | 153 | std::unique_ptr<AudioCore::AudioRenderer> renderer; |
| 143 | u32 rendering_time_limit_percent = 100; | 154 | u32 rendering_time_limit_percent = 100; |
| @@ -235,7 +246,7 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") { | |||
| 235 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, | 246 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, |
| 236 | {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, | 247 | {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, |
| 237 | {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, | 248 | {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, |
| 238 | {3, nullptr, "OpenAudioRendererAuto"}, | 249 | {3, &AudRenU::OpenAudioRendererAuto, "OpenAudioRendererAuto"}, |
| 239 | {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, | 250 | {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, |
| 240 | }; | 251 | }; |
| 241 | // clang-format on | 252 | // clang-format on |
| @@ -248,12 +259,7 @@ AudRenU::~AudRenU() = default; | |||
| 248 | void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { | 259 | void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { |
| 249 | LOG_DEBUG(Service_Audio, "called"); | 260 | LOG_DEBUG(Service_Audio, "called"); |
| 250 | 261 | ||
| 251 | IPC::RequestParser rp{ctx}; | 262 | OpenAudioRendererImpl(ctx); |
| 252 | auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); | ||
| 253 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 254 | |||
| 255 | rb.Push(RESULT_SUCCESS); | ||
| 256 | rb.PushIpcInterface<Audio::IAudioRenderer>(std::move(params)); | ||
| 257 | } | 263 | } |
| 258 | 264 | ||
| 259 | void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | 265 | void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { |
| @@ -325,6 +331,12 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { | |||
| 325 | rb.PushIpcInterface<Audio::IAudioDevice>(); | 331 | rb.PushIpcInterface<Audio::IAudioDevice>(); |
| 326 | } | 332 | } |
| 327 | 333 | ||
| 334 | void AudRenU::OpenAudioRendererAuto(Kernel::HLERequestContext& ctx) { | ||
| 335 | LOG_DEBUG(Service_Audio, "called"); | ||
| 336 | |||
| 337 | OpenAudioRendererImpl(ctx); | ||
| 338 | } | ||
| 339 | |||
| 328 | void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) { | 340 | void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) { |
| 329 | LOG_WARNING(Service_Audio, "(STUBBED) called"); | 341 | LOG_WARNING(Service_Audio, "(STUBBED) called"); |
| 330 | 342 | ||
| @@ -335,6 +347,15 @@ void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& c | |||
| 335 | // based on the current revision | 347 | // based on the current revision |
| 336 | } | 348 | } |
| 337 | 349 | ||
| 350 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { | ||
| 351 | IPC::RequestParser rp{ctx}; | ||
| 352 | const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); | ||
| 353 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 354 | |||
| 355 | rb.Push(RESULT_SUCCESS); | ||
| 356 | rb.PushIpcInterface<IAudioRenderer>(params); | ||
| 357 | } | ||
| 358 | |||
| 338 | bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { | 359 | bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { |
| 339 | u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap | 360 | u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap |
| 340 | switch (feature) { | 361 | switch (feature) { |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 3d63388fb..e55d25973 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -21,8 +21,11 @@ private: | |||
| 21 | void OpenAudioRenderer(Kernel::HLERequestContext& ctx); | 21 | void OpenAudioRenderer(Kernel::HLERequestContext& ctx); |
| 22 | void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); | 22 | void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); |
| 23 | void GetAudioDeviceService(Kernel::HLERequestContext& ctx); | 23 | void GetAudioDeviceService(Kernel::HLERequestContext& ctx); |
| 24 | void OpenAudioRendererAuto(Kernel::HLERequestContext& ctx); | ||
| 24 | void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); | 25 | void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); |
| 25 | 26 | ||
| 27 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); | ||
| 28 | |||
| 26 | enum class AudioFeatures : u32 { | 29 | enum class AudioFeatures : u32 { |
| 27 | Splitter, | 30 | Splitter, |
| 28 | }; | 31 | }; |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 60529323e..3e9d2b3be 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -104,6 +104,8 @@ add_library(video_core STATIC | |||
| 104 | if (ENABLE_VULKAN) | 104 | if (ENABLE_VULKAN) |
| 105 | target_sources(video_core PRIVATE | 105 | target_sources(video_core PRIVATE |
| 106 | renderer_vulkan/declarations.h | 106 | renderer_vulkan/declarations.h |
| 107 | renderer_vulkan/vk_buffer_cache.cpp | ||
| 108 | renderer_vulkan/vk_buffer_cache.h | ||
| 107 | renderer_vulkan/vk_device.cpp | 109 | renderer_vulkan/vk_device.cpp |
| 108 | renderer_vulkan/vk_device.h | 110 | renderer_vulkan/vk_device.h |
| 109 | renderer_vulkan/vk_memory_manager.cpp | 111 | renderer_vulkan/vk_memory_manager.cpp |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 5fdf1164d..b5a9722f9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -966,7 +966,7 @@ Surface RasterizerCacheOpenGL::GetColorBufferSurface(std::size_t index, bool pre | |||
| 966 | const auto& regs{gpu.regs}; | 966 | const auto& regs{gpu.regs}; |
| 967 | 967 | ||
| 968 | if (!gpu.dirty_flags.color_buffer[index]) { | 968 | if (!gpu.dirty_flags.color_buffer[index]) { |
| 969 | return last_color_buffers[index]; | 969 | return current_color_buffers[index]; |
| 970 | } | 970 | } |
| 971 | gpu.dirty_flags.color_buffer.reset(index); | 971 | gpu.dirty_flags.color_buffer.reset(index); |
| 972 | 972 | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp new file mode 100644 index 000000000..18b7b94a1 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cstring> | ||
| 6 | #include <memory> | ||
| 7 | #include <optional> | ||
| 8 | #include <tuple> | ||
| 9 | |||
| 10 | #include "common/alignment.h" | ||
| 11 | #include "core/core.h" | ||
| 12 | #include "core/memory.h" | ||
| 13 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||
| 15 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 16 | #include "video_core/renderer_vulkan/vk_stream_buffer.h" | ||
| 17 | |||
| 18 | namespace Vulkan { | ||
| 19 | |||
| 20 | VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, | ||
| 21 | VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, | ||
| 22 | VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size) | ||
| 23 | : RasterizerCache{rasterizer}, tegra_memory_manager{tegra_memory_manager} { | ||
| 24 | const auto usage = vk::BufferUsageFlagBits::eVertexBuffer | | ||
| 25 | vk::BufferUsageFlagBits::eIndexBuffer | | ||
| 26 | vk::BufferUsageFlagBits::eUniformBuffer; | ||
| 27 | const auto access = vk::AccessFlagBits::eVertexAttributeRead | vk::AccessFlagBits::eIndexRead | | ||
| 28 | vk::AccessFlagBits::eUniformRead; | ||
| 29 | stream_buffer = | ||
| 30 | std::make_unique<VKStreamBuffer>(device, memory_manager, scheduler, size, usage, access, | ||
| 31 | vk::PipelineStageFlagBits::eAllCommands); | ||
| 32 | buffer_handle = stream_buffer->GetBuffer(); | ||
| 33 | } | ||
| 34 | |||
| 35 | VKBufferCache::~VKBufferCache() = default; | ||
| 36 | |||
| 37 | u64 VKBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, u64 alignment, | ||
| 38 | bool cache) { | ||
| 39 | const auto cpu_addr{tegra_memory_manager.GpuToCpuAddress(gpu_addr)}; | ||
| 40 | ASSERT(cpu_addr); | ||
| 41 | |||
| 42 | // Cache management is a big overhead, so only cache entries with a given size. | ||
| 43 | // TODO: Figure out which size is the best for given games. | ||
| 44 | cache &= size >= 2048; | ||
| 45 | |||
| 46 | if (cache) { | ||
| 47 | if (auto entry = TryGet(*cpu_addr); entry) { | ||
| 48 | if (entry->size >= size && entry->alignment == alignment) { | ||
| 49 | return entry->offset; | ||
| 50 | } | ||
| 51 | Unregister(entry); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | AlignBuffer(alignment); | ||
| 56 | const u64 uploaded_offset = buffer_offset; | ||
| 57 | |||
| 58 | Memory::ReadBlock(*cpu_addr, buffer_ptr, size); | ||
| 59 | |||
| 60 | buffer_ptr += size; | ||
| 61 | buffer_offset += size; | ||
| 62 | |||
| 63 | if (cache) { | ||
| 64 | auto entry = std::make_shared<CachedBufferEntry>(); | ||
| 65 | entry->offset = uploaded_offset; | ||
| 66 | entry->size = size; | ||
| 67 | entry->alignment = alignment; | ||
| 68 | entry->addr = *cpu_addr; | ||
| 69 | Register(entry); | ||
| 70 | } | ||
| 71 | |||
| 72 | return uploaded_offset; | ||
| 73 | } | ||
| 74 | |||
| 75 | u64 VKBufferCache::UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment) { | ||
| 76 | AlignBuffer(alignment); | ||
| 77 | std::memcpy(buffer_ptr, raw_pointer, size); | ||
| 78 | const u64 uploaded_offset = buffer_offset; | ||
| 79 | |||
| 80 | buffer_ptr += size; | ||
| 81 | buffer_offset += size; | ||
| 82 | return uploaded_offset; | ||
| 83 | } | ||
| 84 | |||
| 85 | std::tuple<u8*, u64> VKBufferCache::ReserveMemory(std::size_t size, u64 alignment) { | ||
| 86 | AlignBuffer(alignment); | ||
| 87 | u8* const uploaded_ptr = buffer_ptr; | ||
| 88 | const u64 uploaded_offset = buffer_offset; | ||
| 89 | |||
| 90 | buffer_ptr += size; | ||
| 91 | buffer_offset += size; | ||
| 92 | return {uploaded_ptr, uploaded_offset}; | ||
| 93 | } | ||
| 94 | |||
| 95 | void VKBufferCache::Reserve(std::size_t max_size) { | ||
| 96 | bool invalidate; | ||
| 97 | std::tie(buffer_ptr, buffer_offset_base, invalidate) = stream_buffer->Reserve(max_size); | ||
| 98 | buffer_offset = buffer_offset_base; | ||
| 99 | |||
| 100 | if (invalidate) { | ||
| 101 | InvalidateAll(); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | VKExecutionContext VKBufferCache::Send(VKExecutionContext exctx) { | ||
| 106 | return stream_buffer->Send(exctx, buffer_offset - buffer_offset_base); | ||
| 107 | } | ||
| 108 | |||
| 109 | void VKBufferCache::AlignBuffer(std::size_t alignment) { | ||
| 110 | // Align the offset, not the mapped pointer | ||
| 111 | const u64 offset_aligned = Common::AlignUp(buffer_offset, alignment); | ||
| 112 | buffer_ptr += offset_aligned - buffer_offset; | ||
| 113 | buffer_offset = offset_aligned; | ||
| 114 | } | ||
| 115 | |||
| 116 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h new file mode 100644 index 000000000..d8e916f31 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <tuple> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "video_core/gpu.h" | ||
| 12 | #include "video_core/rasterizer_cache.h" | ||
| 13 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 15 | |||
| 16 | namespace Tegra { | ||
| 17 | class MemoryManager; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Vulkan { | ||
| 21 | |||
| 22 | class VKDevice; | ||
| 23 | class VKFence; | ||
| 24 | class VKMemoryManager; | ||
| 25 | class VKStreamBuffer; | ||
| 26 | |||
| 27 | struct CachedBufferEntry final : public RasterizerCacheObject { | ||
| 28 | VAddr GetAddr() const override { | ||
| 29 | return addr; | ||
| 30 | } | ||
| 31 | |||
| 32 | std::size_t GetSizeInBytes() const override { | ||
| 33 | return size; | ||
| 34 | } | ||
| 35 | |||
| 36 | // We do not have to flush this cache as things in it are never modified by us. | ||
| 37 | void Flush() override {} | ||
| 38 | |||
| 39 | VAddr addr; | ||
| 40 | std::size_t size; | ||
| 41 | u64 offset; | ||
| 42 | std::size_t alignment; | ||
| 43 | }; | ||
| 44 | |||
| 45 | class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> { | ||
| 46 | public: | ||
| 47 | explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, | ||
| 48 | VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, | ||
| 49 | VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size); | ||
| 50 | ~VKBufferCache(); | ||
| 51 | |||
| 52 | /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been | ||
| 53 | /// allocated. | ||
| 54 | u64 UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, u64 alignment = 4, | ||
| 55 | bool cache = true); | ||
| 56 | |||
| 57 | /// Uploads from a host memory. Returns host's buffer offset where it's been allocated. | ||
| 58 | u64 UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment = 4); | ||
| 59 | |||
| 60 | /// Reserves memory to be used by host's CPU. Returns mapped address and offset. | ||
| 61 | std::tuple<u8*, u64> ReserveMemory(std::size_t size, u64 alignment = 4); | ||
| 62 | |||
| 63 | /// Reserves a region of memory to be used in subsequent upload/reserve operations. | ||
| 64 | void Reserve(std::size_t max_size); | ||
| 65 | |||
| 66 | /// Ensures that the set data is sent to the device. | ||
| 67 | [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx); | ||
| 68 | |||
| 69 | /// Returns the buffer cache handle. | ||
| 70 | vk::Buffer GetBuffer() const { | ||
| 71 | return buffer_handle; | ||
| 72 | } | ||
| 73 | |||
| 74 | private: | ||
| 75 | void AlignBuffer(std::size_t alignment); | ||
| 76 | |||
| 77 | Tegra::MemoryManager& tegra_memory_manager; | ||
| 78 | |||
| 79 | std::unique_ptr<VKStreamBuffer> stream_buffer; | ||
| 80 | vk::Buffer buffer_handle; | ||
| 81 | |||
| 82 | u8* buffer_ptr = nullptr; | ||
| 83 | u64 buffer_offset = 0; | ||
| 84 | u64 buffer_offset_base = 0; | ||
| 85 | }; | ||
| 86 | |||
| 87 | } // namespace Vulkan | ||
diff --git a/src/web_service/verify_login.h b/src/web_service/verify_login.h index 39db32dbb..821b345d7 100644 --- a/src/web_service/verify_login.h +++ b/src/web_service/verify_login.h | |||
| @@ -4,8 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <functional> | ||
| 8 | #include <future> | ||
| 9 | #include <string> | 7 | #include <string> |
| 10 | 8 | ||
| 11 | namespace WebService { | 9 | namespace WebService { |
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp index b7737b615..40da1a4e2 100644 --- a/src/web_service/web_backend.cpp +++ b/src/web_service/web_backend.cpp | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/web_result.h" | 12 | #include "common/web_result.h" |
| 13 | #include "core/settings.h" | ||
| 14 | #include "web_service/web_backend.h" | 13 | #include "web_service/web_backend.h" |
| 15 | 14 | ||
| 16 | namespace WebService { | 15 | namespace WebService { |
diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp index 5f0896f84..c09a06520 100644 --- a/src/yuzu/compatdb.cpp +++ b/src/yuzu/compatdb.cpp | |||
| @@ -61,7 +61,7 @@ void CompatDB::Submit() { | |||
| 61 | button(QWizard::CancelButton)->setVisible(false); | 61 | button(QWizard::CancelButton)->setVisible(false); |
| 62 | 62 | ||
| 63 | testcase_watcher.setFuture(QtConcurrent::run( | 63 | testcase_watcher.setFuture(QtConcurrent::run( |
| 64 | [this]() { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); })); | 64 | [] { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); })); |
| 65 | break; | 65 | break; |
| 66 | default: | 66 | default: |
| 67 | LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); | 67 | LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 1d460c189..5ab7896d4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -561,7 +561,10 @@ void GMainWindow::InitializeHotkeys() { | |||
| 561 | Settings::values.use_frame_limit = !Settings::values.use_frame_limit; | 561 | Settings::values.use_frame_limit = !Settings::values.use_frame_limit; |
| 562 | UpdateStatusBar(); | 562 | UpdateStatusBar(); |
| 563 | }); | 563 | }); |
| 564 | constexpr u16 SPEED_LIMIT_STEP = 5; | 564 | // TODO: Remove this comment/static whenever the next major release of |
| 565 | // MSVC occurs and we make it a requirement (see: | ||
| 566 | // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html) | ||
| 567 | static constexpr u16 SPEED_LIMIT_STEP = 5; | ||
| 565 | connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), | 568 | connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), |
| 566 | &QShortcut::activated, this, [&] { | 569 | &QShortcut::activated, this, [&] { |
| 567 | if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { | 570 | if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { |