diff options
Diffstat (limited to '')
-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 |
12 files changed, 268 insertions, 43 deletions
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: Impl(Impl const&) = delete; const Impl& operator=(Impl const&) = delete; - void PushEntry(Entry e) { - message_queue.Push(std::move(e)); + void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, + const char* function, std::string message) { + message_queue.Push( + CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); } void AddBackend(std::unique_ptr<Backend> backend) { @@ -108,11 +110,30 @@ private: backend_thread.join(); } + Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, + const char* function, std::string message) const { + using std::chrono::duration_cast; + using std::chrono::steady_clock; + + Entry entry; + entry.timestamp = + duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); + entry.log_class = log_class; + entry.log_level = log_level; + entry.filename = Common::TrimSourcePath(filename); + entry.line_num = line_nr; + entry.function = function; + entry.message = std::move(message); + + return entry; + } + std::mutex writing_mutex; std::thread backend_thread; std::vector<std::unique_ptr<Backend>> backends; Common::MPSCQueue<Log::Entry> message_queue; Filter filter; + std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; }; void ConsoleBackend::Write(const Entry& entry) { @@ -271,25 +292,6 @@ const char* GetLevelName(Level log_level) { #undef LVL } -Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, - const char* function, std::string message) { - using std::chrono::duration_cast; - using std::chrono::steady_clock; - - static steady_clock::time_point time_origin = steady_clock::now(); - - Entry entry; - entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); - entry.log_class = log_class; - entry.log_level = log_level; - entry.filename = Common::TrimSourcePath(filename); - entry.line_num = line_nr; - entry.function = function; - entry.message = std::move(message); - - return entry; -} - void SetGlobalFilter(const Filter& filter) { Impl::Instance().SetGlobalFilter(filter); } @@ -314,9 +316,7 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, if (!filter.CheckMessage(log_class, log_level)) return; - Entry entry = - CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); - - instance.PushEntry(std::move(entry)); + instance.PushEntry(log_class, log_level, filename, line_num, function, + fmt::vformat(format, args)); } } // 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); */ const char* GetLevelName(Level log_level); -/// Creates a log entry by formatting the given source location, and message. -Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, - const char* function, std::string message); - /** * The global filter will prevent any messages from even being processed if they are filtered. Each * 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: {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, {10, &IAudioRenderer::RequestUpdateImpl, "RequestUpdateAuto"}, - {11, nullptr, "ExecuteAudioRendererRendering"}, + {11, &IAudioRenderer::ExecuteAudioRendererRendering, "ExecuteAudioRendererRendering"}, }; // clang-format on RegisterHandlers(functions); @@ -138,6 +138,17 @@ private: rb.Push(rendering_time_limit_percent); } + void ExecuteAudioRendererRendering(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + // This service command currently only reports an unsupported operation + // error code, or aborts. Given that, we just always return an error + // code in this case. + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode{ErrorModule::Audio, 201}); + } + Kernel::EventPair system_event; std::unique_ptr<AudioCore::AudioRenderer> renderer; u32 rendering_time_limit_percent = 100; @@ -235,7 +246,7 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") { {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, - {3, nullptr, "OpenAudioRendererAuto"}, + {3, &AudRenU::OpenAudioRendererAuto, "OpenAudioRendererAuto"}, {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, }; // clang-format on @@ -248,12 +259,7 @@ AudRenU::~AudRenU() = default; void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); - IPC::RequestParser rp{ctx}; - auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<Audio::IAudioRenderer>(std::move(params)); + OpenAudioRendererImpl(ctx); } void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { @@ -325,6 +331,12 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<Audio::IAudioDevice>(); } +void AudRenU::OpenAudioRendererAuto(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + OpenAudioRendererImpl(ctx); +} + void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_Audio, "(STUBBED) called"); @@ -335,6 +347,15 @@ void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& c // based on the current revision } +void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IAudioRenderer>(params); +} + bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap 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: void OpenAudioRenderer(Kernel::HLERequestContext& ctx); void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); void GetAudioDeviceService(Kernel::HLERequestContext& ctx); + void OpenAudioRendererAuto(Kernel::HLERequestContext& ctx); void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); + void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); + enum class AudioFeatures : u32 { Splitter, }; 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 if (ENABLE_VULKAN) target_sources(video_core PRIVATE renderer_vulkan/declarations.h + renderer_vulkan/vk_buffer_cache.cpp + renderer_vulkan/vk_buffer_cache.h renderer_vulkan/vk_device.cpp renderer_vulkan/vk_device.h 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 const auto& regs{gpu.regs}; if (!gpu.dirty_flags.color_buffer[index]) { - return last_color_buffers[index]; + return current_color_buffers[index]; } gpu.dirty_flags.color_buffer.reset(index); 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 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cstring> +#include <memory> +#include <optional> +#include <tuple> + +#include "common/alignment.h" +#include "core/core.h" +#include "core/memory.h" +#include "video_core/renderer_vulkan/declarations.h" +#include "video_core/renderer_vulkan/vk_buffer_cache.h" +#include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/renderer_vulkan/vk_stream_buffer.h" + +namespace Vulkan { + +VKBufferCache::VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, + VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, + VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size) + : RasterizerCache{rasterizer}, tegra_memory_manager{tegra_memory_manager} { + const auto usage = vk::BufferUsageFlagBits::eVertexBuffer | + vk::BufferUsageFlagBits::eIndexBuffer | + vk::BufferUsageFlagBits::eUniformBuffer; + const auto access = vk::AccessFlagBits::eVertexAttributeRead | vk::AccessFlagBits::eIndexRead | + vk::AccessFlagBits::eUniformRead; + stream_buffer = + std::make_unique<VKStreamBuffer>(device, memory_manager, scheduler, size, usage, access, + vk::PipelineStageFlagBits::eAllCommands); + buffer_handle = stream_buffer->GetBuffer(); +} + +VKBufferCache::~VKBufferCache() = default; + +u64 VKBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, u64 alignment, + bool cache) { + const auto cpu_addr{tegra_memory_manager.GpuToCpuAddress(gpu_addr)}; + ASSERT(cpu_addr); + + // Cache management is a big overhead, so only cache entries with a given size. + // TODO: Figure out which size is the best for given games. + cache &= size >= 2048; + + if (cache) { + if (auto entry = TryGet(*cpu_addr); entry) { + if (entry->size >= size && entry->alignment == alignment) { + return entry->offset; + } + Unregister(entry); + } + } + + AlignBuffer(alignment); + const u64 uploaded_offset = buffer_offset; + + Memory::ReadBlock(*cpu_addr, buffer_ptr, size); + + buffer_ptr += size; + buffer_offset += size; + + if (cache) { + auto entry = std::make_shared<CachedBufferEntry>(); + entry->offset = uploaded_offset; + entry->size = size; + entry->alignment = alignment; + entry->addr = *cpu_addr; + Register(entry); + } + + return uploaded_offset; +} + +u64 VKBufferCache::UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment) { + AlignBuffer(alignment); + std::memcpy(buffer_ptr, raw_pointer, size); + const u64 uploaded_offset = buffer_offset; + + buffer_ptr += size; + buffer_offset += size; + return uploaded_offset; +} + +std::tuple<u8*, u64> VKBufferCache::ReserveMemory(std::size_t size, u64 alignment) { + AlignBuffer(alignment); + u8* const uploaded_ptr = buffer_ptr; + const u64 uploaded_offset = buffer_offset; + + buffer_ptr += size; + buffer_offset += size; + return {uploaded_ptr, uploaded_offset}; +} + +void VKBufferCache::Reserve(std::size_t max_size) { + bool invalidate; + std::tie(buffer_ptr, buffer_offset_base, invalidate) = stream_buffer->Reserve(max_size); + buffer_offset = buffer_offset_base; + + if (invalidate) { + InvalidateAll(); + } +} + +VKExecutionContext VKBufferCache::Send(VKExecutionContext exctx) { + return stream_buffer->Send(exctx, buffer_offset - buffer_offset_base); +} + +void VKBufferCache::AlignBuffer(std::size_t alignment) { + // Align the offset, not the mapped pointer + const u64 offset_aligned = Common::AlignUp(buffer_offset, alignment); + buffer_ptr += offset_aligned - buffer_offset; + buffer_offset = offset_aligned; +} + +} // 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 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <tuple> + +#include "common/common_types.h" +#include "video_core/gpu.h" +#include "video_core/rasterizer_cache.h" +#include "video_core/renderer_vulkan/declarations.h" +#include "video_core/renderer_vulkan/vk_scheduler.h" + +namespace Tegra { +class MemoryManager; +} + +namespace Vulkan { + +class VKDevice; +class VKFence; +class VKMemoryManager; +class VKStreamBuffer; + +struct CachedBufferEntry final : public RasterizerCacheObject { + VAddr GetAddr() const override { + return addr; + } + + std::size_t GetSizeInBytes() const override { + return size; + } + + // We do not have to flush this cache as things in it are never modified by us. + void Flush() override {} + + VAddr addr; + std::size_t size; + u64 offset; + std::size_t alignment; +}; + +class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> { +public: + explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, + VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, + VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size); + ~VKBufferCache(); + + /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been + /// allocated. + u64 UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, u64 alignment = 4, + bool cache = true); + + /// Uploads from a host memory. Returns host's buffer offset where it's been allocated. + u64 UploadHostMemory(const u8* raw_pointer, std::size_t size, u64 alignment = 4); + + /// Reserves memory to be used by host's CPU. Returns mapped address and offset. + std::tuple<u8*, u64> ReserveMemory(std::size_t size, u64 alignment = 4); + + /// Reserves a region of memory to be used in subsequent upload/reserve operations. + void Reserve(std::size_t max_size); + + /// Ensures that the set data is sent to the device. + [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx); + + /// Returns the buffer cache handle. + vk::Buffer GetBuffer() const { + return buffer_handle; + } + +private: + void AlignBuffer(std::size_t alignment); + + Tegra::MemoryManager& tegra_memory_manager; + + std::unique_ptr<VKStreamBuffer> stream_buffer; + vk::Buffer buffer_handle; + + u8* buffer_ptr = nullptr; + u64 buffer_offset = 0; + u64 buffer_offset_base = 0; +}; + +} // 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 @@ #pragma once -#include <functional> -#include <future> #include <string> 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 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/web_result.h" -#include "core/settings.h" #include "web_service/web_backend.h" 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() { button(QWizard::CancelButton)->setVisible(false); testcase_watcher.setFuture(QtConcurrent::run( - [this]() { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); })); + [] { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); })); break; default: 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() { Settings::values.use_frame_limit = !Settings::values.use_frame_limit; UpdateStatusBar(); }); - constexpr u16 SPEED_LIMIT_STEP = 5; + // TODO: Remove this comment/static whenever the next major release of + // MSVC occurs and we make it a requirement (see: + // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html) + static constexpr u16 SPEED_LIMIT_STEP = 5; connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), &QShortcut::activated, this, [&] { if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { |