Compare commits

...

4 Commits

Author SHA1 Message Date
TheLastRar
4daa455524 GS/VK: Fix the Nvidia present fix 2026-01-20 21:54:14 +01:00
TheLastRar
433e99baec GS/VK: Hackfix impatient present on Nvidia 2026-01-20 08:03:00 +01:00
Ty
a1ac6662d3 QT: Focus the main window when the DisplayWidget is focused to get its toolbar 2026-01-19 09:31:55 -05:00
JordanTheToaster
87366cda9d 3rdparty: Update rcheevos to 12.2.1 2026-01-18 10:35:14 -05:00
8 changed files with 60 additions and 6 deletions

View File

@@ -1,3 +1,7 @@
# v12.2.1
* fix parsing of leaderboards with comparisons in legacy-formatted values
* fix validation warning on long AddSource chains
# v12.2.0
* add rc_client_create_subset_list
* add rc_client_begin_fetch_game_titles

View File

@@ -9,7 +9,7 @@ RC_BEGIN_C_DECLS
#define RCHEEVOS_VERSION_MAJOR 12
#define RCHEEVOS_VERSION_MINOR 2
#define RCHEEVOS_VERSION_PATCH 0
#define RCHEEVOS_VERSION_PATCH 1
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
#define RCHEEVOS_VERSION RCHEEVOS_MAKE_VERSION(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH)

View File

@@ -510,6 +510,7 @@ static void rc_combine_ranges(uint32_t* min_val, uint32_t* max_val, uint8_t oper
break;
case RC_OPERATOR_ADD:
case RC_OPERATOR_ADD_ACCUMULATOR:
if (*min_val > *max_val) { /* underflow occurred */
*max_val += oper_max_val;
}
@@ -522,6 +523,7 @@ static void rc_combine_ranges(uint32_t* min_val, uint32_t* max_val, uint8_t oper
break;
case RC_OPERATOR_SUB:
case RC_OPERATOR_SUB_ACCUMULATOR:
*min_val -= oper_max_val;
*max_val -= oper_min_val;
break;

View File

@@ -180,9 +180,11 @@ static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_par
return;
}
if (!rc_operator_is_modifying(cond->oper)) {
parse->offset = RC_INVALID_OPERATOR;
return;
if (cond->type == RC_CONDITION_MEASURED && !rc_operator_is_modifying(cond->oper)) {
/* ignore non-modifying operator on measured clause. if it were parsed as an AddSource
* or SubSource, that would have already happened in rc_parse_condition_internal, and
* legacy formatted values are essentially a series of AddSources. */
cond->oper = RC_OPERATOR_NONE;
}
rc_condition_update_parse_state(cond, parse);

View File

@@ -477,6 +477,13 @@ bool DisplaySurface::eventFilter(QObject* object, QEvent* event)
}
return false;
case QEvent::FocusIn:
// macOS: When we (the display window) get focus from another window with a toolbar we update to the MainWindow toolbar.
// This is because we are a different native window from our MainWindow. So, whenever we get focus, focus our MainWindow.
// That way macOS will show the MainWindow toolbar when you click from the debugger / log window to the game.
if (auto* w = qobject_cast<QWidget*>(object))
w->window()->activateWindow();
return false;
default:
return false;
}

View File

@@ -1348,13 +1348,29 @@ void GSDeviceVK::SubmitCommandBuffer(VKSwapChain* present_swap_chain)
if (present_swap_chain)
{
// vkQueuePresentKHR on NVidia dosn't seem to properly wait on the passed semaphore, causing artifacts.
// OBS capture with BPM encouters issues, but can apparently occur on the presented image aswell.
// Instead, wait on the RenderingFinished semaphore with vkQueueSubmit.
const uint32_t present_wait_bits = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
const VkSubmitInfo submit_present_wait_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1,
present_swap_chain->GetRenderingFinishedSemaphorePtr(), &present_wait_bits, 0,
nullptr, 1, present_swap_chain->GetPresentReadySemaphorePtr()};
res = vkQueueSubmit(m_present_queue, 1, &submit_present_wait_info, nullptr);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkQueueSubmit failed: ");
m_last_submit_failed = true;
return;
}
const VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, nullptr, 1,
present_swap_chain->GetRenderingFinishedSemaphorePtr(), 1, present_swap_chain->GetSwapChainPtr(),
present_swap_chain->GetPresentReadySemaphorePtr(), 1, present_swap_chain->GetSwapChainPtr(),
present_swap_chain->GetCurrentImageIndexPtr(), nullptr};
present_swap_chain->ResetImageAcquireResult();
const VkResult res = vkQueuePresentKHR(m_present_queue, &present_info);
res = vkQueuePresentKHR(m_present_queue, &present_info);
if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR)
{
// VK_ERROR_OUT_OF_DATE_KHR is not fatal, just means we need to recreate our swap chain.

View File

@@ -490,6 +490,18 @@ bool VKSwapChain::CreateSwapChain()
sema.available_semaphore = VK_NULL_HANDLE;
return false;
}
res = vkCreateSemaphore(
GSDeviceVK::GetInstance()->GetDevice(), &semaphore_info, nullptr, &sema.present_ready_semaphore);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: ");
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), sema.rendering_finished_semaphore, nullptr);
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), sema.available_semaphore, nullptr);
sema.rendering_finished_semaphore = VK_NULL_HANDLE;
sema.available_semaphore = VK_NULL_HANDLE;
return false;
}
}
return true;
@@ -505,6 +517,8 @@ void VKSwapChain::DestroySwapChainImages()
m_images.clear();
for (auto& it : m_semaphores)
{
if (it.present_ready_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.present_ready_semaphore, nullptr);
if (it.rendering_finished_semaphore != VK_NULL_HANDLE)
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.rendering_finished_semaphore, nullptr);
if (it.available_semaphore != VK_NULL_HANDLE)

View File

@@ -64,6 +64,14 @@ public:
{
return &m_semaphores[m_current_semaphore].rendering_finished_semaphore;
}
__fi VkSemaphore GetPresentReadySemaphore() const
{
return m_semaphores[m_current_semaphore].present_ready_semaphore;
}
__fi const VkSemaphore* GetPresentReadySemaphorePtr() const
{
return &m_semaphores[m_current_semaphore].present_ready_semaphore;
}
VkFormat GetTextureFormat() const;
VkResult AcquireNextImage();
@@ -92,6 +100,7 @@ private:
{
VkSemaphore available_semaphore;
VkSemaphore rendering_finished_semaphore;
VkSemaphore present_ready_semaphore;
};
WindowInfo m_window_info;