Skip to content

Commit 2e3fce3

Browse files
committed
vulkan: Add support for VK_AMD_anti_lag.
Qt port will use it when "Reduce Input Lag" option is enabled.
1 parent 121bb37 commit 2e3fce3

6 files changed

Lines changed: 93 additions & 22 deletions

File tree

common/video/vulkan/vulkan_context.cpp

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,6 @@ bool Context::init_device()
235235
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
236236
};
237237

238-
std::vector<const char *> present_wait_extensions =
239-
{
240-
VK_KHR_PRESENT_ID_EXTENSION_NAME,
241-
VK_KHR_PRESENT_WAIT_EXTENSION_NAME
242-
};
243-
244238
auto device_list = instance->enumeratePhysicalDevices().value;
245239
bool device_chosen = false;
246240
physical_device = vk::PhysicalDevice();
@@ -269,15 +263,36 @@ bool Context::init_device()
269263
if (!device_chosen)
270264
return false;
271265

272-
if (check_extensions(present_wait_extensions, physical_device))
266+
auto chain = physical_device.getFeatures2<vk::PhysicalDeviceFeatures2,
267+
vk::PhysicalDeviceAntiLagFeaturesAMD,
268+
vk::PhysicalDevicePresentWaitFeaturesKHR>();
269+
270+
if (chain.isLinked<vk::PhysicalDevicePresentWaitFeaturesKHR>())
273271
{
274-
for (auto &ext : present_wait_extensions)
275-
required_extensions.push_back(ext);
276-
have_present_wait = true;
272+
std::vector<const char *> present_wait_extensions = {
273+
VK_KHR_PRESENT_ID_EXTENSION_NAME,
274+
VK_KHR_PRESENT_WAIT_EXTENSION_NAME
275+
};
276+
277+
if (chain.get<vk::PhysicalDevicePresentWaitFeaturesKHR>().presentWait &&
278+
check_extensions(present_wait_extensions, physical_device))
279+
{
280+
for (auto &ext : present_wait_extensions)
281+
required_extensions.push_back(ext);
282+
have_present_wait = true;
283+
}
277284
}
278-
else
285+
286+
if (chain.isLinked<vk::PhysicalDeviceAntiLagFeaturesAMD>())
279287
{
280-
have_present_wait = false;
288+
std::vector<const char *> anti_lag_extensions = { VK_AMD_ANTI_LAG_EXTENSION_NAME };
289+
290+
if (chain.get<vk::PhysicalDeviceAntiLagFeaturesAMD>().antiLag &&
291+
check_extensions(anti_lag_extensions, physical_device))
292+
{
293+
required_extensions.push_back(anti_lag_extensions[0]);
294+
have_anti_lag = true;
295+
}
281296
}
282297

283298
if (auto index = find_graphics_queue(physical_device))
@@ -289,13 +304,12 @@ bool Context::init_device()
289304
vk::DeviceQueueCreateInfo dqci({}, graphics_queue_family_index, priorities);
290305
vk::DeviceCreateInfo dci({}, dqci, {}, required_extensions);
291306

292-
vk::PhysicalDevicePresentWaitFeaturesKHR physical_device_present_wait_feature(true);
293-
vk::PhysicalDevicePresentIdFeaturesKHR physical_device_present_id_feature(true);
294-
if (have_present_wait)
295-
{
296-
dci.setPNext(&physical_device_present_wait_feature);
297-
physical_device_present_wait_feature.setPNext(&physical_device_present_id_feature);
298-
}
307+
vk::PhysicalDevicePresentWaitFeaturesKHR physical_device_present_wait_feature(have_present_wait);
308+
dci.setPNext(&physical_device_present_wait_feature);
309+
vk::PhysicalDevicePresentIdFeaturesKHR physical_device_present_id_feature(have_present_wait);
310+
physical_device_present_wait_feature.setPNext(&physical_device_present_id_feature);
311+
vk::PhysicalDeviceAntiLagFeaturesAMD physical_device_anti_lag_feature(have_anti_lag);
312+
physical_device_present_id_feature.setPNext(&physical_device_anti_lag_feature);
299313

300314
device = physical_device.createDevice(dci).value;
301315
queue = device.getQueue(graphics_queue_family_index, 0);
@@ -319,6 +333,37 @@ bool Context::init_vma()
319333
return true;
320334
}
321335

336+
bool Context::update_anti_lag_stage(vk::AntiLagStageAMD stage)
337+
{
338+
if (!have_anti_lag || !device)
339+
return false;
340+
341+
vk::AntiLagPresentationInfoAMD pinfo;
342+
vk::AntiLagDataAMD data;
343+
344+
pinfo.setFrameIndex(anti_lag_frame_index);
345+
pinfo.setStage(stage);
346+
data.setPPresentationInfo(&pinfo);
347+
data.setMaxFPS(0);
348+
data.setMode(vk::AntiLagModeAMD::eOn);
349+
device.antiLagUpdateAMD(data);
350+
351+
if (stage == vk::AntiLagStageAMD::ePresent)
352+
anti_lag_frame_index++;
353+
354+
return true;
355+
}
356+
357+
bool Context::update_anti_lag_input()
358+
{
359+
return update_anti_lag_stage(vk::AntiLagStageAMD::eInput);
360+
}
361+
362+
bool Context::update_anti_lag_present()
363+
{
364+
return update_anti_lag_stage(vk::AntiLagStageAMD::ePresent);
365+
}
366+
322367
bool Context::create_swapchain()
323368
{
324369
wait_idle();

common/video/vulkan/vulkan_context.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class Context
4141
vk::CommandBuffer begin_cmd_buffer();
4242
void end_cmd_buffer();
4343
void hard_barrier(vk::CommandBuffer cmd);
44+
bool update_anti_lag_stage(vk::AntiLagStageAMD);
45+
bool update_anti_lag_input();
46+
bool update_anti_lag_present();
4447
static std::vector<std::string> get_device_list();
4548
void set_preferred_device(int device) { preferred_device = device; };
4649
void unset_preferred_device() { preferred_device = -1; };
@@ -56,13 +59,15 @@ class Context
5659
vk::PhysicalDeviceProperties physical_device_props;
5760
vk::UniqueSurfaceKHR surface;
5861
std::string platform_name;
59-
bool have_present_wait;
62+
bool have_present_wait{};
63+
bool have_anti_lag{};
64+
uint64_t anti_lag_frame_index{};
6065

6166
private:
6267
bool init_vma();
6368
bool init_device();
6469
bool init_command_pool();
65-
int preferred_device;
70+
int preferred_device{};
6671

6772
#ifdef VK_USE_PLATFORM_XLIB_KHR
6873
Display *xlib_display;

qt/src/EmuApplication.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ void EmuApplication::mainLoop()
259259
return;
260260
}
261261

262+
if (window->canvas)
263+
window->canvas->signalInputStage();
264+
265+
QGuiApplication::processEvents();
266+
262267
core->mainLoop();
263268
}
264269

qt/src/EmuCanvas.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class EmuCanvas : public QWidget
6565
virtual void showParametersDialog() {};
6666
virtual void shaderChanged() {};
6767
virtual void saveParameters(std::string filename) {};
68+
virtual void signalInputStage() {};
6869

6970
struct
7071
{

qt/src/EmuCanvasVulkan.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,18 @@ void EmuCanvasVulkan::draw()
215215
if (retval)
216216
{
217217
throttle();
218+
bool anti_lag_used = config->reduce_input_lag ? context->update_anti_lag_present() : false;
218219
context->swapchain->swap();
219-
if (config->reduce_input_lag)
220+
if (config->reduce_input_lag && !anti_lag_used)
220221
{
221222
context->wait_idle();
222223
context->swapchain->present_wait();
223224
}
224225
}
225226
}
226227

228+
229+
227230
void EmuCanvasVulkan::resizeEvent(QResizeEvent *event)
228231
{
229232
QWidget::resizeEvent(event);
@@ -331,6 +334,17 @@ void EmuCanvasVulkan::showParametersDialog()
331334
shader_parameters_dialog->show();
332335
}
333336

337+
void EmuCanvasVulkan::signalInputStage()
338+
{
339+
if (!context)
340+
return;
341+
342+
if (!config->reduce_input_lag)
343+
return;
344+
345+
context->update_anti_lag_input();
346+
}
347+
334348
void EmuCanvasVulkan::saveParameters(std::string filename)
335349
{
336350
if (shader_chain && shader_chain->preset)

qt/src/EmuCanvasVulkan.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class EmuCanvasVulkan : public EmuCanvas
2525
void shaderChanged() override;
2626
void showParametersDialog() override;
2727
void saveParameters(std::string filename) override;
28+
void signalInputStage() override;
2829

2930
void draw() override;
3031

0 commit comments

Comments
 (0)