diff options
Diffstat (limited to 'src')
23 files changed, 253 insertions, 60 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index ac3ff9f20..0477ce66e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -338,7 +338,54 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c LOG_WARNING(Service_AM, "(STUBBED) called"); } -ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { +AppletMessageQueue::AppletMessageQueue() { + auto& kernel = Core::System::GetInstance().Kernel(); + on_new_message = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, + "AMMessageQueue:OnMessageRecieved"); + on_operation_mode_changed = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "AMMessageQueue:OperationModeChanged"); +} + +AppletMessageQueue::~AppletMessageQueue() = default; + +const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetMesssageRecieveEvent() const { + return on_new_message; +} + +const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetOperationModeChangedEvent() const { + return on_operation_mode_changed; +} + +void AppletMessageQueue::PushMessage(AppletMessage msg) { + messages.push(msg); + on_new_message->Signal(); +} + +AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { + if (messages.empty()) { + on_new_message->Clear(); + return AppletMessage::NoMessage; + } + auto msg = messages.front(); + messages.pop(); + if (messages.empty()) { + on_new_message->Clear(); + } + return msg; +} + +std::size_t AppletMessageQueue::GetMessageCount() const { + return messages.size(); +} + +void AppletMessageQueue::OperationModeChanged() { + PushMessage(AppletMessage::OperationModeChanged); + PushMessage(AppletMessage::PerformanceModeChanged); + on_operation_mode_changed->Signal(); +} + +ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("ICommonStateGetter"), msg_queue(std::move(msg_queue)) { // clang-format off static const FunctionInfo functions[] = { {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, @@ -388,21 +435,19 @@ void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) { } void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) { - event->Signal(); - IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); + rb.PushCopyObjects(msg_queue->GetMesssageRecieveEvent()); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(15); + rb.PushEnum<AppletMessageQueue::AppletMessage>(msg_queue->PopMessage()); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { @@ -414,13 +459,11 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { } void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) { - event->Signal(); - IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); + rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent()); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx) { @@ -444,7 +487,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { @@ -454,7 +497,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked : APM::PerformanceMode::Handheld)); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { @@ -840,8 +883,12 @@ void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) { void InstallInterfaces(SM::ServiceManager& service_manager, std::shared_ptr<NVFlinger::NVFlinger> nvflinger) { - std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager); - std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager); + auto message_queue = std::make_shared<AppletMessageQueue>(); + message_queue->PushMessage( + AppletMessageQueue::AppletMessage::FocusStateChanged); // Needed on game boot + + std::make_shared<AppletAE>(nvflinger, message_queue)->InstallAsService(service_manager); + std::make_shared<AppletOE>(nvflinger, message_queue)->InstallAsService(service_manager); std::make_shared<IdleSys>()->InstallAsService(service_manager); std::make_shared<OMM>()->InstallAsService(service_manager); std::make_shared<SPSM>()->InstallAsService(service_manager); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 095f94851..2f1c20bce 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -5,6 +5,7 @@ #pragma once #include <memory> +#include <queue> #include "core/hle/service/service.h" namespace Kernel { @@ -39,6 +40,31 @@ enum SystemLanguage { TraditionalChinese = 16, }; +class AppletMessageQueue { +public: + enum class AppletMessage : u32 { + NoMessage = 0, + FocusStateChanged = 15, + OperationModeChanged = 30, + PerformanceModeChanged = 31, + }; + + AppletMessageQueue(); + ~AppletMessageQueue(); + + const Kernel::SharedPtr<Kernel::Event>& GetMesssageRecieveEvent() const; + const Kernel::SharedPtr<Kernel::Event>& GetOperationModeChangedEvent() const; + void PushMessage(AppletMessage msg); + AppletMessage PopMessage(); + std::size_t GetMessageCount() const; + void OperationModeChanged(); + +private: + std::queue<AppletMessage> messages; + Kernel::SharedPtr<Kernel::Event> on_new_message; + Kernel::SharedPtr<Kernel::Event> on_operation_mode_changed; +}; + class IWindowController final : public ServiceFramework<IWindowController> { public: IWindowController(); @@ -102,7 +128,7 @@ private: class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { public: - ICommonStateGetter(); + explicit ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue); ~ICommonStateGetter() override; private: @@ -126,6 +152,7 @@ private: void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); Kernel::SharedPtr<Kernel::Event> event; + std::shared_ptr<AppletMessageQueue> msg_queue; }; class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index 68ea778e8..ec93e3529 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -12,8 +12,10 @@ namespace Service::AM { class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { public: - explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)) { + explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { static const FunctionInfo functions[] = { {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, @@ -32,7 +34,7 @@ private: void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ICommonStateGetter>(); + rb.PushIpcInterface<ICommonStateGetter>(msg_queue); LOG_DEBUG(Service_AM, "called"); } @@ -93,12 +95,15 @@ private: } std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { public: - explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)) { + explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { static const FunctionInfo functions[] = { {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, @@ -119,7 +124,7 @@ private: void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ICommonStateGetter>(); + rb.PushIpcInterface<ICommonStateGetter>(msg_queue); LOG_DEBUG(Service_AM, "called"); } @@ -186,31 +191,34 @@ private: LOG_DEBUG(Service_AM, "called"); } std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISystemAppletProxy>(nvflinger); + rb.PushIpcInterface<ISystemAppletProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } void AppletAE::OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger); + rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger); + rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } -AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)) { +AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { // clang-format off static const FunctionInfo functions[] = { {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, @@ -228,4 +236,8 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) AppletAE::~AppletAE() = default; +const std::shared_ptr<AppletMessageQueue>& AppletAE::GetMessageQueue() const { + return msg_queue; +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 1ed77baa4..902db2665 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h @@ -17,15 +17,19 @@ namespace AM { class AppletAE final : public ServiceFramework<AppletAE> { public: - explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); + explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue); ~AppletAE() override; + const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; + private: void OpenSystemAppletProxy(Kernel::HLERequestContext& ctx); void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx); void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; } // namespace AM diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index 60717afd9..20c8d5fff 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -12,8 +12,10 @@ namespace Service::AM { class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { public: - explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)) { + explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { // clang-format off static const FunctionInfo functions[] = { {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -70,7 +72,7 @@ private: void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ICommonStateGetter>(); + rb.PushIpcInterface<ICommonStateGetter>(msg_queue); LOG_DEBUG(Service_AM, "called"); } @@ -89,17 +91,20 @@ private: } std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IApplicationProxy>(nvflinger); + rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue); LOG_DEBUG(Service_AM, "called"); } -AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)) { +AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue) + : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)), + msg_queue(std::move(msg_queue)) { static const FunctionInfo functions[] = { {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, }; @@ -108,4 +113,8 @@ AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) AppletOE::~AppletOE() = default; +const std::shared_ptr<AppletMessageQueue>& AppletOE::GetMessageQueue() const { + return msg_queue; +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 60cfdfd9d..bbd0108ef 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -17,13 +17,17 @@ namespace AM { class AppletOE final : public ServiceFramework<AppletOE> { public: - explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); + explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, + std::shared_ptr<AppletMessageQueue> msg_queue); ~AppletOE() override; + const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; + private: void OpenApplicationProxy(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + std::shared_ptr<AppletMessageQueue> msg_queue; }; } // namespace AM diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 0b1cc1290..a780215c1 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(video_core STATIC macro_interpreter.h memory_manager.cpp memory_manager.h + rasterizer_cache.cpp rasterizer_cache.h rasterizer_interface.h renderer_base.cpp diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 2cd595f26..5ae836aca 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -108,8 +108,16 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); } + u32 old = regs.reg_array[method]; regs.reg_array[method] = value; + if (value != old) { + if (method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) && + method < MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { + dirty_flags.vertex_attrib_format = true; + } + } + switch (method) { case MAXWELL3D_REG_INDEX(macros.data): { ProcessMacroUpload(value); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 0509ba3a2..557795d0f 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -1004,6 +1004,12 @@ public: State state{}; MemoryManager& memory_manager; + struct DirtyFlags { + bool vertex_attrib_format = true; + }; + + DirtyFlags dirty_flags; + /// Reads a register value located at the input method address u32 GetRegisterValue(u32 method) const; diff --git a/src/video_core/rasterizer_cache.cpp b/src/video_core/rasterizer_cache.cpp new file mode 100644 index 000000000..093b2cdf4 --- /dev/null +++ b/src/video_core/rasterizer_cache.cpp @@ -0,0 +1,7 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "video_core/rasterizer_cache.h" + +RasterizerCacheObject::~RasterizerCacheObject() = default; diff --git a/src/video_core/rasterizer_cache.h b/src/video_core/rasterizer_cache.h index 0a3b3951e..6d41321fa 100644 --- a/src/video_core/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache.h @@ -10,13 +10,13 @@ #include <boost/range/iterator_range_core.hpp> #include "common/common_types.h" -#include "core/core.h" #include "core/settings.h" #include "video_core/rasterizer_interface.h" -#include "video_core/renderer_base.h" class RasterizerCacheObject { public: + virtual ~RasterizerCacheObject(); + /// Gets the address of the shader in guest memory, required for cache management virtual VAddr GetAddr() const = 0; @@ -64,6 +64,8 @@ class RasterizerCache : NonCopyable { friend class RasterizerCacheObject; public: + explicit RasterizerCache(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {} + /// Write any cached resources overlapping the specified region back to memory void FlushRegion(Tegra::GPUVAddr addr, size_t size) { const auto& objects{GetSortedObjectsFromRegion(addr, size)}; @@ -109,14 +111,12 @@ protected: void Register(const T& object) { object->SetIsRegistered(true); object_cache.add({GetInterval(object), ObjectSet{object}}); - auto& rasterizer = Core::System::GetInstance().Renderer().Rasterizer(); rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), 1); } /// Unregisters an object from the cache void Unregister(const T& object) { object->SetIsRegistered(false); - auto& rasterizer = Core::System::GetInstance().Renderer().Rasterizer(); rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), -1); // Only flush if use_accurate_gpu_emulation is enabled, as it incurs a performance hit @@ -177,4 +177,5 @@ private: ObjectCache object_cache; ///< Cache of objects u64 modified_ticks{}; ///< Counter of cache state ticks, used for in-order flushing + VideoCore::RasterizerInterface& rasterizer; }; diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 41a54b3e7..075192c3f 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp @@ -9,10 +9,12 @@ #include "core/core.h" #include "core/memory.h" #include "video_core/renderer_opengl/gl_buffer_cache.h" +#include "video_core/renderer_opengl/gl_rasterizer.h" namespace OpenGL { -OGLBufferCache::OGLBufferCache(std::size_t size) : stream_buffer(GL_ARRAY_BUFFER, size) {} +OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size) + : RasterizerCache{rasterizer}, stream_buffer(GL_ARRAY_BUFFER, size) {} GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, std::size_t alignment, bool cache) { diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index be29dc8be..91fca3f6c 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -15,6 +15,8 @@ namespace OpenGL { +class RasterizerOpenGL; + struct CachedBufferEntry final : public RasterizerCacheObject { VAddr GetAddr() const override { return addr; @@ -35,7 +37,7 @@ struct CachedBufferEntry final : public RasterizerCacheObject { class OGLBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> { public: - explicit OGLBufferCache(std::size_t size); + explicit OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size); /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been /// allocated. diff --git a/src/video_core/renderer_opengl/gl_primitive_assembler.cpp b/src/video_core/renderer_opengl/gl_primitive_assembler.cpp index 741f14bc3..d9ed08437 100644 --- a/src/video_core/renderer_opengl/gl_primitive_assembler.cpp +++ b/src/video_core/renderer_opengl/gl_primitive_assembler.cpp @@ -6,6 +6,7 @@ #include <array> #include "common/assert.h" #include "common/common_types.h" +#include "core/core.h" #include "core/memory.h" #include "video_core/renderer_opengl/gl_buffer_cache.h" #include "video_core/renderer_opengl/gl_primitive_assembler.h" diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index bb263b6aa..a404764f5 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -33,7 +33,8 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs; using PixelFormat = VideoCore::Surface::PixelFormat; using SurfaceType = VideoCore::Surface::SurfaceType; -MICROPROFILE_DEFINE(OpenGL_VAO, "OpenGL", "Vertex Array Setup", MP_RGB(128, 128, 192)); +MICROPROFILE_DEFINE(OpenGL_VAO, "OpenGL", "Vertex Format Setup", MP_RGB(128, 128, 192)); +MICROPROFILE_DEFINE(OpenGL_VB, "OpenGL", "Vertex Buffer Setup", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_Shader, "OpenGL", "Shader Setup", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_UBO, "OpenGL", "Const Buffer Setup", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_Index, "OpenGL", "Index Buffer Setup", MP_RGB(128, 128, 192)); @@ -79,7 +80,8 @@ struct DrawParameters { }; RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info) - : emu_window{window}, screen_info{info}, buffer_cache(STREAM_BUFFER_SIZE) { + : res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info}, + buffer_cache(*this, STREAM_BUFFER_SIZE) { // Create sampler objects for (std::size_t i = 0; i < texture_samplers.size(); ++i) { texture_samplers[i].Create(); @@ -122,11 +124,16 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo RasterizerOpenGL::~RasterizerOpenGL() {} -void RasterizerOpenGL::SetupVertexArrays() { - MICROPROFILE_SCOPE(OpenGL_VAO); - const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); +void RasterizerOpenGL::SetupVertexFormat() { + auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); const auto& regs = gpu.regs; + if (!gpu.dirty_flags.vertex_attrib_format) + return; + gpu.dirty_flags.vertex_attrib_format = false; + + MICROPROFILE_SCOPE(OpenGL_VAO); + auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format); auto& VAO = iter->second; @@ -175,8 +182,13 @@ void RasterizerOpenGL::SetupVertexArrays() { } } state.draw.vertex_array = VAO.handle; - state.draw.vertex_buffer = buffer_cache.GetHandle(); state.Apply(); +} + +void RasterizerOpenGL::SetupVertexBuffer() { + MICROPROFILE_SCOPE(OpenGL_VB); + const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); + const auto& regs = gpu.regs; // Upload all guest vertex arrays sequentially to our buffer for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) { @@ -203,6 +215,9 @@ void RasterizerOpenGL::SetupVertexArrays() { glVertexBindingDivisor(index, 0); } } + + // Implicit set by glBindVertexBuffer. Stupid glstate handling... + state.draw.vertex_buffer = buffer_cache.GetHandle(); } DrawParameters RasterizerOpenGL::SetupDraw() { @@ -620,7 +635,8 @@ void RasterizerOpenGL::DrawArrays() { buffer_cache.Map(buffer_size); - SetupVertexArrays(); + SetupVertexFormat(); + SetupVertexBuffer(); DrawParameters params = SetupDraw(); SetupShaders(params.primitive_mode); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 60e783803..5eee5f088 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -207,7 +207,8 @@ private: std::size_t CalculateIndexBufferSize() const; - void SetupVertexArrays(); + void SetupVertexFormat(); + void SetupVertexBuffer(); DrawParameters SetupDraw(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 49d63e6f3..c8864cce8 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -15,6 +15,7 @@ #include "core/memory.h" #include "core/settings.h" #include "video_core/engines/maxwell_3d.h" +#include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_rasterizer_cache.h" #include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/utils.h" @@ -1172,7 +1173,8 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); } -RasterizerCacheOpenGL::RasterizerCacheOpenGL() { +RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer) + : RasterizerCache{rasterizer} { read_framebuffer.Create(); draw_framebuffer.Create(); copy_pbo.Create(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index c0b6bc4e6..494f6b903 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -264,6 +264,8 @@ struct hash<SurfaceReserveKey> { namespace OpenGL { +class RasterizerOpenGL; + class CachedSurface final : public RasterizerCacheObject { public: CachedSurface(const SurfaceParams& params); @@ -311,7 +313,7 @@ private: class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { public: - RasterizerCacheOpenGL(); + explicit RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer); /// Get a surface based on the texture configuration Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config, diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 31ccf4ab8..a85a7c0c5 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -6,10 +6,10 @@ #include "core/core.h" #include "core/memory.h" #include "video_core/engines/maxwell_3d.h" +#include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_cache.h" #include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/utils.h" -#include "video_core/utils.h" namespace OpenGL { @@ -139,6 +139,8 @@ GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, return target_program.handle; }; +ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} {} + Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { const VAddr program_addr{GetShaderAddress(program)}; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 8fd0b7e88..ffbf21831 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -16,6 +16,8 @@ namespace OpenGL { class CachedShader; +class RasterizerOpenGL; + using Shader = std::shared_ptr<CachedShader>; using Maxwell = Tegra::Engines::Maxwell3D::Regs; @@ -105,6 +107,8 @@ private: class ShaderCacheOpenGL final : public RasterizerCache<Shader> { public: + explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer); + /// Gets the current specified shader stage program Shader GetStageProgram(Maxwell::ShaderProgram program); }; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index bce7465b5..5fde22ad4 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -2746,12 +2746,12 @@ private: } case 3: { if (is_array) { - UNIMPLEMENTED_MSG("3-coordinate arrays not fully implemented"); - const std::string x = regs.GetRegisterAsFloat(instr.gpr8); - const std::string y = regs.GetRegisterAsFloat(instr.gpr20); - coord = "vec2 coords = vec2(" + x + ", " + y + ");"; - texture_type = Tegra::Shader::TextureType::Texture2D; - is_array = false; + const std::string index = regs.GetRegisterAsInteger(instr.gpr8); + const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); + const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); + const std::string z = regs.GetRegisterAsFloat(instr.gpr20); + coord = + "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + index + ");"; } else { const std::string x = regs.GetRegisterAsFloat(instr.gpr8); const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); @@ -2781,7 +2781,11 @@ private: break; } case Tegra::Shader::TextureProcessMode::LZ: { - texture = "textureLod(" + sampler + ", coords, 0.0)"; + if (depth_compare && is_array) { + texture = "texture(" + sampler + ", coords)"; + } else { + texture = "textureLod(" + sampler + ", coords, 0.0)"; + } break; } case Tegra::Shader::TextureProcessMode::LL: { diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 537d6e576..b322258a0 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -3,6 +3,10 @@ // Refer to the license.txt file included. #include "core/core.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/am/applet_oe.h" +#include "core/hle/service/sm/sm.h" #include "core/settings.h" #include "ui_configure_general.h" #include "yuzu/configuration/configure_general.h" @@ -20,7 +24,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) this->setConfiguration(); ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); - ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); } ConfigureGeneral::~ConfigureGeneral() = default; @@ -38,6 +41,30 @@ void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { ui->widget->Populate(registry); } +void ConfigureGeneral::OnDockedModeChanged(bool last_state, bool new_state) { + if (last_state == new_state) { + return; + } + + Core::System& system{Core::System::GetInstance()}; + Service::SM::ServiceManager& sm = system.ServiceManager(); + + // Message queue is shared between these services, we just need to signal an operation + // change to one and it will handle both automatically + auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE"); + auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE"); + bool has_signalled = false; + + if (applet_oe != nullptr) { + applet_oe->GetMessageQueue()->OperationModeChanged(); + has_signalled = true; + } + + if (applet_ae != nullptr && !has_signalled) { + applet_ae->GetMessageQueue()->OperationModeChanged(); + } +} + void ConfigureGeneral::applyConfiguration() { UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); @@ -45,6 +72,9 @@ void ConfigureGeneral::applyConfiguration() { ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); + const bool pre_docked_mode = Settings::values.use_docked_mode; Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); + OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); + Settings::values.enable_nfc = ui->enable_nfc->isChecked(); } diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 4770034cc..2210d48da 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -25,6 +25,7 @@ public: private: void setConfiguration(); + void OnDockedModeChanged(bool last_state, bool new_state); std::unique_ptr<Ui::ConfigureGeneral> ui; }; |