summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/audio_core/stream.cpp2
-rw-r--r--src/audio_core/stream.h25
-rw-r--r--src/core/core_timing.cpp53
-rw-r--r--src/core/core_timing.h45
-rw-r--r--src/core/hardware_interrupt_manager.cpp13
-rw-r--r--src/core/hardware_interrupt_manager.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp13
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/service/hid/hid.cpp5
-rw-r--r--src/core/hle/service/hid/hid.h2
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp4
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h2
-rw-r--r--src/core/memory/cheat_engine.cpp2
-rw-r--r--src/core/memory/cheat_engine.h3
-rw-r--r--src/core/tools/freezer.cpp2
-rw-r--r--src/core/tools/freezer.h3
-rw-r--r--src/tests/core/core_timing.cpp84
-rw-r--r--src/video_core/gpu_thread.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp49
-rw-r--r--src/video_core/renderer_opengl/gl_device.h1
-rw-r--r--src/video_core/shader/const_buffer_locker.cpp10
-rw-r--r--src/video_core/shader/const_buffer_locker.h1
22 files changed, 111 insertions, 217 deletions
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index 6a5f53a57..4ca98f8ea 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -37,7 +37,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
: sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
- release_event = core_timing.RegisterEvent(
+ release_event = Core::Timing::CreateEvent(
name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(); });
}
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 8106cea43..1708a4d98 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -98,18 +98,19 @@ private:
/// Gets the number of core cycles when the specified buffer will be released
s64 GetBufferReleaseCycles(const Buffer& buffer) const;
- u32 sample_rate; ///< Sample rate of the stream
- Format format; ///< Format of the stream
- float game_volume = 1.0f; ///< The volume the game currently has set
- ReleaseCallback release_callback; ///< Buffer release callback for the stream
- State state{State::Stopped}; ///< Playback state of the stream
- Core::Timing::EventType* release_event{}; ///< Core timing release event for the stream
- BufferPtr active_buffer; ///< Actively playing buffer in the stream
- std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
- std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
- SinkStream& sink_stream; ///< Output sink for the stream
- Core::Timing::CoreTiming& core_timing; ///< Core timing instance.
- std::string name; ///< Name of the stream, must be unique
+ u32 sample_rate; ///< Sample rate of the stream
+ Format format; ///< Format of the stream
+ float game_volume = 1.0f; ///< The volume the game currently has set
+ ReleaseCallback release_callback; ///< Buffer release callback for the stream
+ State state{State::Stopped}; ///< Playback state of the stream
+ std::shared_ptr<Core::Timing::EventType>
+ release_event; ///< Core timing release event for the stream
+ BufferPtr active_buffer; ///< Actively playing buffer in the stream
+ std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
+ std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
+ SinkStream& sink_stream; ///< Output sink for the stream
+ Core::Timing::CoreTiming& core_timing; ///< Core timing instance.
+ std::string name; ///< Name of the stream, must be unique
};
using StreamPtr = std::shared_ptr<Stream>;
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 0e9570685..aa09fa453 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -17,11 +17,15 @@ namespace Core::Timing {
constexpr int MAX_SLICE_LENGTH = 10000;
+std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
+ return std::make_shared<EventType>(std::move(callback), std::move(name));
+}
+
struct CoreTiming::Event {
s64 time;
u64 fifo_order;
u64 userdata;
- const EventType* type;
+ std::weak_ptr<EventType> type;
// Sort by time, unless the times are the same, in which case sort by
// the order added to the queue
@@ -54,36 +58,15 @@ void CoreTiming::Initialize() {
event_fifo_id = 0;
const auto empty_timed_callback = [](u64, s64) {};
- ev_lost = RegisterEvent("_lost_event", empty_timed_callback);
+ ev_lost = CreateEvent("_lost_event", empty_timed_callback);
}
void CoreTiming::Shutdown() {
ClearPendingEvents();
- UnregisterAllEvents();
-}
-
-EventType* CoreTiming::RegisterEvent(const std::string& name, TimedCallback callback) {
- std::lock_guard guard{inner_mutex};
- // check for existing type with same name.
- // we want event type names to remain unique so that we can use them for serialization.
- ASSERT_MSG(event_types.find(name) == event_types.end(),
- "CoreTiming Event \"{}\" is already registered. Events should only be registered "
- "during Init to avoid breaking save states.",
- name.c_str());
-
- auto info = event_types.emplace(name, EventType{callback, nullptr});
- EventType* event_type = &info.first->second;
- event_type->name = &info.first->first;
- return event_type;
-}
-
-void CoreTiming::UnregisterAllEvents() {
- ASSERT_MSG(event_queue.empty(), "Cannot unregister events with events pending");
- event_types.clear();
}
-void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
- ASSERT(event_type != nullptr);
+void CoreTiming::ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
+ u64 userdata) {
std::lock_guard guard{inner_mutex};
const s64 timeout = GetTicks() + cycles_into_future;
@@ -93,13 +76,15 @@ void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_ty
}
event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
+
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
}
-void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) {
+void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) {
std::lock_guard guard{inner_mutex};
+
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
- return e.type == event_type && e.userdata == userdata;
+ return e.type.lock().get() == event_type.get() && e.userdata == userdata;
});
// Removing random items breaks the invariant so we have to re-establish it.
@@ -130,10 +115,12 @@ void CoreTiming::ClearPendingEvents() {
event_queue.clear();
}
-void CoreTiming::RemoveEvent(const EventType* event_type) {
+void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
std::lock_guard guard{inner_mutex};
- const auto itr = std::remove_if(event_queue.begin(), event_queue.end(),
- [&](const Event& e) { return e.type == event_type; });
+
+ const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
+ return e.type.lock().get() == event_type.get();
+ });
// Removing random items breaks the invariant so we have to re-establish it.
if (itr != event_queue.end()) {
@@ -181,7 +168,11 @@ void CoreTiming::Advance() {
std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
event_queue.pop_back();
inner_mutex.unlock();
- evt.type->callback(evt.userdata, global_timer - evt.time);
+
+ if (auto event_type{evt.type.lock()}) {
+ event_type->callback(evt.userdata, global_timer - evt.time);
+ }
+
inner_mutex.lock();
}
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 3bb88c810..d50f4eb8a 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -6,11 +6,12 @@
#include <chrono>
#include <functional>
+#include <memory>
#include <mutex>
#include <optional>
#include <string>
-#include <unordered_map>
#include <vector>
+
#include "common/common_types.h"
#include "common/threadsafe_queue.h"
@@ -21,10 +22,13 @@ using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>;
/// Contains the characteristics of a particular event.
struct EventType {
+ EventType(TimedCallback&& callback, std::string&& name)
+ : callback{std::move(callback)}, name{std::move(name)} {}
+
/// The event's callback function.
TimedCallback callback;
/// A pointer to the name of the event.
- const std::string* name;
+ const std::string name;
};
/**
@@ -57,31 +61,17 @@ public:
/// Tears down all timing related functionality.
void Shutdown();
- /// Registers a core timing event with the given name and callback.
- ///
- /// @param name The name of the core timing event to register.
- /// @param callback The callback to execute for the event.
- ///
- /// @returns An EventType instance representing the registered event.
- ///
- /// @pre The name of the event being registered must be unique among all
- /// registered events.
- ///
- EventType* RegisterEvent(const std::string& name, TimedCallback callback);
-
- /// Unregisters all registered events thus far. Note: not thread unsafe
- void UnregisterAllEvents();
-
/// After the first Advance, the slice lengths and the downcount will be reduced whenever an
/// event is scheduled earlier than the current values.
///
/// Scheduling from a callback will not update the downcount until the Advance() completes.
- void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata = 0);
+ void ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
+ u64 userdata = 0);
- void UnscheduleEvent(const EventType* event_type, u64 userdata);
+ void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
/// We only permit one event of each type in the queue at a time.
- void RemoveEvent(const EventType* event_type);
+ void RemoveEvent(const std::shared_ptr<EventType>& event_type);
void ForceExceptionCheck(s64 cycles);
@@ -148,13 +138,18 @@ private:
std::vector<Event> event_queue;
u64 event_fifo_id = 0;
- // Stores each element separately as a linked list node so pointers to elements
- // remain stable regardless of rehashes/resizing.
- std::unordered_map<std::string, EventType> event_types;
-
- EventType* ev_lost = nullptr;
+ std::shared_ptr<EventType> ev_lost;
std::mutex inner_mutex;
};
+/// Creates a core timing event with the given name and callback.
+///
+/// @param name The name of the core timing event to create.
+/// @param callback The callback to execute for the event.
+///
+/// @returns An EventType instance representing the created event.
+///
+std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
+
} // namespace Core::Timing
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp
index c2115db2d..c629d9fa1 100644
--- a/src/core/hardware_interrupt_manager.cpp
+++ b/src/core/hardware_interrupt_manager.cpp
@@ -11,13 +11,12 @@
namespace Core::Hardware {
InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
- gpu_interrupt_event =
- system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 message, s64) {
- auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
- const u32 syncpt = static_cast<u32>(message >> 32);
- const u32 value = static_cast<u32>(message);
- nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
- });
+ gpu_interrupt_event = Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, s64) {
+ auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
+ const u32 syncpt = static_cast<u32>(message >> 32);
+ const u32 value = static_cast<u32>(message);
+ nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
+ });
}
InterruptManager::~InterruptManager() = default;
diff --git a/src/core/hardware_interrupt_manager.h b/src/core/hardware_interrupt_manager.h
index 494db883a..5fa306ae0 100644
--- a/src/core/hardware_interrupt_manager.h
+++ b/src/core/hardware_interrupt_manager.h
@@ -4,6 +4,8 @@
#pragma once
+#include <memory>
+
#include "common/common_types.h"
namespace Core {
@@ -25,7 +27,7 @@ public:
private:
Core::System& system;
- Core::Timing::EventType* gpu_interrupt_event{};
+ std::shared_ptr<Core::Timing::EventType> gpu_interrupt_event;
};
} // namespace Core::Hardware
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 63ad07950..a9851113a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -139,12 +139,12 @@ struct KernelCore::Impl {
void InitializeThreads() {
thread_wakeup_event_type =
- system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
+ Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback);
}
void InitializePreemption() {
- preemption_event = system.CoreTiming().RegisterEvent(
- "PreemptionCallback", [this](u64 userdata, s64 cycles_late) {
+ preemption_event =
+ Core::Timing::CreateEvent("PreemptionCallback", [this](u64 userdata, s64 cycles_late) {
global_scheduler.PreemptThreads();
s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10));
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
@@ -166,8 +166,9 @@ struct KernelCore::Impl {
std::shared_ptr<ResourceLimit> system_resource_limit;
- Core::Timing::EventType* thread_wakeup_event_type = nullptr;
- Core::Timing::EventType* preemption_event = nullptr;
+ std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type;
+ std::shared_ptr<Core::Timing::EventType> preemption_event;
+
// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
// allowing us to simply use a pool index or similar.
Kernel::HandleTable thread_wakeup_callback_handle_table;
@@ -269,7 +270,7 @@ u64 KernelCore::CreateNewUserProcessID() {
return impl->next_user_process_id++;
}
-Core::Timing::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
+const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallbackEventType() const {
return impl->thread_wakeup_event_type;
}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index c74b9078f..babb531c6 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -113,7 +113,7 @@ private:
u64 CreateNewThreadID();
/// Retrieves the event type used for thread wakeup callbacks.
- Core::Timing::EventType* ThreadWakeupCallbackEventType() const;
+ const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const;
/// Provides a reference to the thread wakeup callback handle table.
Kernel::HandleTable& ThreadWakeupCallbackHandleTable();
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 8ef029e0f..89bf8b815 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -77,15 +77,14 @@ IAppletResource::IAppletResource(Core::System& system)
GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000);
// Register update callbacks
- auto& core_timing = system.CoreTiming();
pad_update_event =
- core_timing.RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 cycles_late) {
+ Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 cycles_late) {
UpdateControllers(userdata, cycles_late);
});
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
- core_timing.ScheduleEvent(pad_update_ticks, pad_update_event);
+ system.CoreTiming().ScheduleEvent(pad_update_ticks, pad_update_event);
ReloadInputDevices();
}
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 923762fff..ad20f147c 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -69,7 +69,7 @@ private:
std::shared_ptr<Kernel::SharedMemory> shared_mem;
- Core::Timing::EventType* pad_update_event;
+ std::shared_ptr<Core::Timing::EventType> pad_update_event;
Core::System& system;
std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index cd07ab362..52623cf89 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -37,8 +37,8 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
displays.emplace_back(4, "Null", system);
// Schedule the screen composition events
- composition_event = system.CoreTiming().RegisterEvent(
- "ScreenComposition", [this](u64 userdata, s64 cycles_late) {
+ composition_event =
+ Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 cycles_late) {
Compose();
const auto ticks =
Settings::values.force_30fps_mode ? frame_ticks_30fps : GetNextTicks();
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 9cc41f2e6..e3cc14bdc 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -103,7 +103,7 @@ private:
u32 swap_interval = 1;
/// Event that handles screen composition.
- Core::Timing::EventType* composition_event;
+ std::shared_ptr<Core::Timing::EventType> composition_event;
Core::System& system;
};
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 10821d452..b73cc9fbd 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -186,7 +186,7 @@ CheatEngine::~CheatEngine() {
}
void CheatEngine::Initialize() {
- event = core_timing.RegisterEvent(
+ event = Core::Timing::CreateEvent(
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h
index 0f012e9b5..e3db90dac 100644
--- a/src/core/memory/cheat_engine.h
+++ b/src/core/memory/cheat_engine.h
@@ -5,6 +5,7 @@
#pragma once
#include <atomic>
+#include <memory>
#include <vector>
#include "common/common_types.h"
#include "core/memory/dmnt_cheat_types.h"
@@ -78,7 +79,7 @@ private:
std::vector<CheatEntry> cheats;
std::atomic_bool is_pending_reload{false};
- Core::Timing::EventType* event{};
+ std::shared_ptr<Core::Timing::EventType> event;
Core::Timing::CoreTiming& core_timing;
Core::System& system;
};
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp
index 17f050068..19b531ecb 100644
--- a/src/core/tools/freezer.cpp
+++ b/src/core/tools/freezer.cpp
@@ -54,7 +54,7 @@ void MemoryWriteWidth(u32 width, VAddr addr, u64 value) {
} // Anonymous namespace
Freezer::Freezer(Core::Timing::CoreTiming& core_timing) : core_timing(core_timing) {
- event = core_timing.RegisterEvent(
+ event = Core::Timing::CreateEvent(
"MemoryFreezer::FrameCallback",
[this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event);
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h
index b58de5472..90b1a885c 100644
--- a/src/core/tools/freezer.h
+++ b/src/core/tools/freezer.h
@@ -5,6 +5,7 @@
#pragma once
#include <atomic>
+#include <memory>
#include <mutex>
#include <optional>
#include <vector>
@@ -75,7 +76,7 @@ private:
mutable std::mutex entries_mutex;
std::vector<Entry> entries;
- Core::Timing::EventType* event;
+ std::shared_ptr<Core::Timing::EventType> event;
Core::Timing::CoreTiming& core_timing;
};
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index 3443bf05e..1e3940801 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -7,7 +7,9 @@
#include <array>
#include <bitset>
#include <cstdlib>
+#include <memory>
#include <string>
+
#include "common/file_util.h"
#include "core/core.h"
#include "core/core_timing.h"
@@ -65,11 +67,16 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
ScopeInit guard;
auto& core_timing = guard.core_timing;
- Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
- Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
- Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>);
- Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", CallbackTemplate<3>);
- Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", CallbackTemplate<4>);
+ std::shared_ptr<Core::Timing::EventType> cb_a =
+ Core::Timing::CreateEvent("callbackA", CallbackTemplate<0>);
+ std::shared_ptr<Core::Timing::EventType> cb_b =
+ Core::Timing::CreateEvent("callbackB", CallbackTemplate<1>);
+ std::shared_ptr<Core::Timing::EventType> cb_c =
+ Core::Timing::CreateEvent("callbackC", CallbackTemplate<2>);
+ std::shared_ptr<Core::Timing::EventType> cb_d =
+ Core::Timing::CreateEvent("callbackD", CallbackTemplate<3>);
+ std::shared_ptr<Core::Timing::EventType> cb_e =
+ Core::Timing::CreateEvent("callbackE", CallbackTemplate<4>);
// Enter slice 0
core_timing.ResetRun();
@@ -99,8 +106,8 @@ TEST_CASE("CoreTiming[FairSharing]", "[core]") {
ScopeInit guard;
auto& core_timing = guard.core_timing;
- Core::Timing::EventType* empty_callback =
- core_timing.RegisterEvent("empty_callback", EmptyCallback);
+ std::shared_ptr<Core::Timing::EventType> empty_callback =
+ Core::Timing::CreateEvent("empty_callback", EmptyCallback);
callbacks_done = 0;
u64 MAX_CALLBACKS = 10;
@@ -133,8 +140,10 @@ TEST_CASE("Core::Timing[PredictableLateness]", "[core]") {
ScopeInit guard;
auto& core_timing = guard.core_timing;
- Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
- Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
+ std::shared_ptr<Core::Timing::EventType> cb_a =
+ Core::Timing::CreateEvent("callbackA", CallbackTemplate<0>);
+ std::shared_ptr<Core::Timing::EventType> cb_b =
+ Core::Timing::CreateEvent("callbackB", CallbackTemplate<1>);
// Enter slice 0
core_timing.ResetRun();
@@ -145,60 +154,3 @@ TEST_CASE("Core::Timing[PredictableLateness]", "[core]") {
AdvanceAndCheck(core_timing, 0, 0, 10, -10); // (100 - 10)
AdvanceAndCheck(core_timing, 1, 1, 50, -50);
}
-
-namespace ChainSchedulingTest {
-static int reschedules = 0;
-
-static void RescheduleCallback(Core::Timing::CoreTiming& core_timing, u64 userdata,
- s64 cycles_late) {
- --reschedules;
- REQUIRE(reschedules >= 0);
- REQUIRE(lateness == cycles_late);
-
- if (reschedules > 0) {
- core_timing.ScheduleEvent(1000, reinterpret_cast<Core::Timing::EventType*>(userdata),
- userdata);
- }
-}
-} // namespace ChainSchedulingTest
-
-TEST_CASE("CoreTiming[ChainScheduling]", "[core]") {
- using namespace ChainSchedulingTest;
-
- ScopeInit guard;
- auto& core_timing = guard.core_timing;
-
- Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
- Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
- Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>);
- Core::Timing::EventType* cb_rs = core_timing.RegisterEvent(
- "callbackReschedule", [&core_timing](u64 userdata, s64 cycles_late) {
- RescheduleCallback(core_timing, userdata, cycles_late);
- });
-
- // Enter slice 0
- core_timing.ResetRun();
-
- core_timing.ScheduleEvent(800, cb_a, CB_IDS[0]);
- core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]);
- core_timing.ScheduleEvent(2200, cb_c, CB_IDS[2]);
- core_timing.ScheduleEvent(1000, cb_rs, reinterpret_cast<u64>(cb_rs));
- REQUIRE(800 == core_timing.GetDowncount());
-
- reschedules = 3;
- AdvanceAndCheck(core_timing, 0, 0); // cb_a
- AdvanceAndCheck(core_timing, 1, 1); // cb_b, cb_rs
- REQUIRE(2 == reschedules);
-
- core_timing.AddTicks(core_timing.GetDowncount());
- core_timing.Advance(); // cb_rs
- core_timing.SwitchContext(3);
- REQUIRE(1 == reschedules);
- REQUIRE(200 == core_timing.GetDowncount());
-
- AdvanceAndCheck(core_timing, 2, 3); // cb_c
-
- core_timing.AddTicks(core_timing.GetDowncount());
- core_timing.Advance(); // cb_rs
- REQUIRE(0 == reschedules);
-}
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 3efa3d8d0..2cdf1aa7f 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -71,8 +71,7 @@ void ThreadManager::SubmitList(Tegra::CommandList&& entries) {
}
void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
- PushCommand(SwapBuffersCommand(framebuffer ? *framebuffer
- : std::optional<const Tegra::FramebufferConfig>{}));
+ PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt));
}
void ThreadManager::FlushRegion(CacheAddr addr, u64 size) {
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index a95bd4b2c..413d8546b 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -137,6 +137,7 @@ Device::Device() : base_bindings{BuildBaseBindings()} {
const std::vector extensions = GetExtensions();
const bool is_nvidia = vendor == "NVIDIA Corporation";
+ const bool is_amd = vendor == "ATI Technologies Inc.";
const bool is_intel = vendor == "Intel";
uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
@@ -149,7 +150,7 @@ Device::Device() : base_bindings{BuildBaseBindings()} {
has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array;
has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted");
has_variable_aoffi = TestVariableAoffi();
- has_component_indexing_bug = TestComponentIndexingBug();
+ has_component_indexing_bug = is_amd;
has_precise_bug = TestPreciseBug();
has_broken_compute = is_intel;
has_fast_buffer_sub_data = is_nvidia;
@@ -184,52 +185,6 @@ void main() {
})");
}
-bool Device::TestComponentIndexingBug() {
- const GLchar* COMPONENT_TEST = R"(#version 430 core
-layout (std430, binding = 0) buffer OutputBuffer {
- uint output_value;
-};
-layout (std140, binding = 0) uniform InputBuffer {
- uvec4 input_value[4096];
-};
-layout (location = 0) uniform uint idx;
-void main() {
- output_value = input_value[idx >> 2][idx & 3];
-})";
- const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &COMPONENT_TEST)};
- SCOPE_EXIT({ glDeleteProgram(shader); });
- glUseProgram(shader);
-
- OGLVertexArray vao;
- vao.Create();
- glBindVertexArray(vao.handle);
-
- constexpr std::array<GLuint, 8> values{0, 0, 0, 0, 0x1236327, 0x985482, 0x872753, 0x2378432};
- OGLBuffer ubo;
- ubo.Create();
- glNamedBufferData(ubo.handle, sizeof(values), values.data(), GL_STATIC_DRAW);
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo.handle);
-
- OGLBuffer ssbo;
- ssbo.Create();
- glNamedBufferStorage(ssbo.handle, sizeof(GLuint), nullptr, GL_CLIENT_STORAGE_BIT);
-
- for (GLuint index = 4; index < 8; ++index) {
- glInvalidateBufferData(ssbo.handle);
- glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo.handle);
-
- glProgramUniform1ui(shader, 0, index);
- glDrawArrays(GL_POINTS, 0, 1);
-
- GLuint result;
- glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result);
- if (result != values.at(index)) {
- return true;
- }
- }
- return false;
-}
-
bool Device::TestPreciseBug() {
return !TestProgram(R"(#version 430 core
in vec3 coords;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 5433815b9..d73b099d0 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -86,7 +86,6 @@ public:
private:
static bool TestVariableAoffi();
- static bool TestComponentIndexingBug();
static bool TestPreciseBug();
std::array<BaseBindings, Tegra::Engines::MaxShaderTypes> base_bindings;
diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp
index b65399f91..a4a0319eb 100644
--- a/src/video_core/shader/const_buffer_locker.cpp
+++ b/src/video_core/shader/const_buffer_locker.cpp
@@ -2,11 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#pragma once
-
#include <algorithm>
-#include <memory>
-#include "common/assert.h"
+#include <tuple>
+
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/shader_type.h"
@@ -104,8 +102,8 @@ bool ConstBufferLocker::IsConsistent() const {
}
bool ConstBufferLocker::HasEqualKeys(const ConstBufferLocker& rhs) const {
- return keys == rhs.keys && bound_samplers == rhs.bound_samplers &&
- bindless_samplers == rhs.bindless_samplers;
+ return std::tie(keys, bound_samplers, bindless_samplers) ==
+ std::tie(rhs.keys, rhs.bound_samplers, rhs.bindless_samplers);
}
} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h
index 50a8ce42a..d32e2d657 100644
--- a/src/video_core/shader/const_buffer_locker.h
+++ b/src/video_core/shader/const_buffer_locker.h
@@ -4,6 +4,7 @@
#pragma once
+#include <optional>
#include <unordered_map>
#include "common/common_types.h"
#include "common/hash.h"