mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 07:29:17 +01:00
[dxvk] Add GPU event class
GPU events allow for finer-grained CPU<>GPU synchronization than the current approach, so we should change our implementation.
This commit is contained in:
parent
7fa2fb5188
commit
4da89ccc48
103
src/dxvk/dxvk_gpu_event.cpp
Normal file
103
src/dxvk/dxvk_gpu_event.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "dxvk_gpu_event.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
DxvkGpuEvent::DxvkGpuEvent(const Rc<vk::DeviceFn>& vkd)
|
||||||
|
: m_vkd(vkd) { }
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEvent::~DxvkGpuEvent() {
|
||||||
|
if (m_handle.pool && m_handle.event)
|
||||||
|
m_handle.pool->freeEvent(m_handle.event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEventStatus DxvkGpuEvent::test() const {
|
||||||
|
if (!m_handle.event)
|
||||||
|
return DxvkGpuEventStatus::Invalid;
|
||||||
|
|
||||||
|
VkResult status = m_vkd->vkGetEventStatus(
|
||||||
|
m_vkd->device(), m_handle.event);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case VK_EVENT_SET: return DxvkGpuEventStatus::Signaled;
|
||||||
|
case VK_EVENT_RESET: return DxvkGpuEventStatus::Pending;
|
||||||
|
default: return DxvkGpuEventStatus::Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEventHandle DxvkGpuEvent::reset(DxvkGpuEventHandle handle) {
|
||||||
|
m_vkd->vkResetEvent(m_vkd->device(), handle.event);
|
||||||
|
return std::exchange(m_handle, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEventPool::DxvkGpuEventPool(const Rc<vk::DeviceFn>& vkd)
|
||||||
|
: m_vkd(vkd) { }
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEventPool::~DxvkGpuEventPool() {
|
||||||
|
for (VkEvent ev : m_events)
|
||||||
|
m_vkd->vkDestroyEvent(m_vkd->device(), ev, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEventHandle DxvkGpuEventPool::allocEvent() {
|
||||||
|
VkEvent event = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_events.size() > 0) {
|
||||||
|
event = m_events.back();
|
||||||
|
m_events.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event) {
|
||||||
|
VkEventCreateInfo info;
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
||||||
|
info.pNext = nullptr;
|
||||||
|
info.flags = 0;
|
||||||
|
|
||||||
|
VkResult status = m_vkd->vkCreateEvent(
|
||||||
|
m_vkd->device(), &info, nullptr, &event);
|
||||||
|
|
||||||
|
if (status != VK_SUCCESS) {
|
||||||
|
Logger::err("DXVK: Failed to create GPU event");
|
||||||
|
return DxvkGpuEventHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { this, event };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkGpuEventPool::freeEvent(VkEvent event) {
|
||||||
|
std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||||
|
m_events.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGpuEventTracker::DxvkGpuEventTracker() { }
|
||||||
|
DxvkGpuEventTracker::~DxvkGpuEventTracker() { }
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkGpuEventTracker::trackEvent(DxvkGpuEventHandle handle) {
|
||||||
|
if (handle.pool && handle.event)
|
||||||
|
m_handles.push_back(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkGpuEventTracker::reset() {
|
||||||
|
for (const auto& h : m_handles)
|
||||||
|
h.pool->freeEvent(h.event);
|
||||||
|
|
||||||
|
m_handles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
153
src/dxvk/dxvk_gpu_event.h
Normal file
153
src/dxvk/dxvk_gpu_event.h
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "dxvk_resource.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
class DxvkGpuEventPool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Event status
|
||||||
|
*
|
||||||
|
* Reports whether the event is in
|
||||||
|
* a signaled or unsignaled state.
|
||||||
|
*/
|
||||||
|
enum class DxvkGpuEventStatus : uint32_t {
|
||||||
|
Invalid = 0,
|
||||||
|
Pending = 1,
|
||||||
|
Signaled = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Event handle
|
||||||
|
*
|
||||||
|
* Stores the event handle itself as well
|
||||||
|
* as a pointer to the pool that the event
|
||||||
|
* was allocated from.
|
||||||
|
*/
|
||||||
|
struct DxvkGpuEventHandle {
|
||||||
|
DxvkGpuEventPool* pool = nullptr;
|
||||||
|
VkEvent event = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief GPU event
|
||||||
|
*
|
||||||
|
* An event managed by the GPU which allows
|
||||||
|
* the application to check whether a specific
|
||||||
|
* command has completed execution.
|
||||||
|
*/
|
||||||
|
class DxvkGpuEvent : public DxvkResource {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkGpuEvent(const Rc<vk::DeviceFn>& vkd);
|
||||||
|
~DxvkGpuEvent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves event status
|
||||||
|
*
|
||||||
|
* Only valid after the event has been
|
||||||
|
* recorded intro a command buffer.
|
||||||
|
* \returns Event status
|
||||||
|
*/
|
||||||
|
DxvkGpuEventStatus test() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Resets event
|
||||||
|
*
|
||||||
|
* Assigns a new Vulkan event to this event
|
||||||
|
* object and replaces the old one. The old
|
||||||
|
* event should be freed as soon as the GPU
|
||||||
|
* stops using it.
|
||||||
|
* \param [in] handle New GPU event handle
|
||||||
|
* \returns Old GPU event handle
|
||||||
|
*/
|
||||||
|
DxvkGpuEventHandle reset(DxvkGpuEventHandle handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
DxvkGpuEventHandle m_handle;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Event pool
|
||||||
|
*
|
||||||
|
* Thread-safe event allocator that provides
|
||||||
|
* a way to create and recycle Vulkan events.
|
||||||
|
*/
|
||||||
|
class DxvkGpuEventPool : public RcObject {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkGpuEventPool(const Rc<vk::DeviceFn>& vkd);
|
||||||
|
~DxvkGpuEventPool();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Allocates an event
|
||||||
|
*
|
||||||
|
* Either returns a recycled event, or
|
||||||
|
* creates a new one if necessary. The
|
||||||
|
* state of the event is undefined.
|
||||||
|
* \returns An event handle
|
||||||
|
*/
|
||||||
|
DxvkGpuEventHandle allocEvent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Recycles an event
|
||||||
|
*
|
||||||
|
* \param [in] handle Event to free
|
||||||
|
*/
|
||||||
|
void freeEvent(VkEvent event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Rc<vk::DeviceFn> m_vkd;
|
||||||
|
sync::Spinlock m_mutex;
|
||||||
|
std::vector<VkEvent> m_events;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief GPU event tracker
|
||||||
|
*
|
||||||
|
* Stores events currently accessed by the
|
||||||
|
* GPU, and returns them to the event pool
|
||||||
|
* once they are no longer in use.
|
||||||
|
*/
|
||||||
|
class DxvkGpuEventTracker {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkGpuEventTracker();
|
||||||
|
~DxvkGpuEventTracker();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Tracks an event
|
||||||
|
* \param [in] handle Event to track
|
||||||
|
*/
|
||||||
|
void trackEvent(DxvkGpuEventHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Resets event tracker
|
||||||
|
*
|
||||||
|
* Releases all tracked events back
|
||||||
|
* to the respective event pool
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector<DxvkGpuEventHandle> m_handles;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -55,6 +55,7 @@ dxvk_src = files([
|
|||||||
'dxvk_event.cpp',
|
'dxvk_event.cpp',
|
||||||
'dxvk_format.cpp',
|
'dxvk_format.cpp',
|
||||||
'dxvk_framebuffer.cpp',
|
'dxvk_framebuffer.cpp',
|
||||||
|
'dxvk_gpu_event.cpp',
|
||||||
'dxvk_graphics.cpp',
|
'dxvk_graphics.cpp',
|
||||||
'dxvk_image.cpp',
|
'dxvk_image.cpp',
|
||||||
'dxvk_instance.cpp',
|
'dxvk_instance.cpp',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user