2017-12-16 18:10:55 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <condition_variable>
|
|
|
|
#include <mutex>
|
|
|
|
#include <queue>
|
|
|
|
|
2018-07-16 18:45:54 +02:00
|
|
|
#include "../util/thread.h"
|
2018-11-28 12:32:09 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
#include "../vulkan/vulkan_presenter.h"
|
|
|
|
|
2017-12-16 18:10:55 +01:00
|
|
|
#include "dxvk_cmdlist.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
class DxvkDevice;
|
2019-05-05 14:08:07 +02:00
|
|
|
|
2019-07-05 14:27:45 +02:00
|
|
|
/**
|
|
|
|
* \brief Submission status
|
|
|
|
*
|
|
|
|
* Stores the result of a queue
|
|
|
|
* submission or a present call.
|
|
|
|
*/
|
|
|
|
struct DxvkSubmitStatus {
|
|
|
|
std::atomic<VkResult> result = { VK_SUCCESS };
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
/**
|
|
|
|
* \brief Queue submission info
|
|
|
|
*
|
|
|
|
* Stores parameters used to submit
|
|
|
|
* a command buffer to the device.
|
|
|
|
*/
|
|
|
|
struct DxvkSubmitInfo {
|
|
|
|
Rc<DxvkCommandList> cmdList;
|
|
|
|
VkSemaphore waitSync;
|
|
|
|
VkSemaphore wakeSync;
|
|
|
|
};
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Present info
|
|
|
|
*
|
|
|
|
* Stores parameters used to present
|
|
|
|
* a swap chain image on the device.
|
|
|
|
*/
|
|
|
|
struct DxvkPresentInfo {
|
|
|
|
Rc<vk::Presenter> presenter;
|
|
|
|
VkSemaphore waitSync;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-07-05 14:27:45 +02:00
|
|
|
/**
|
|
|
|
* \brief Submission queue entry
|
|
|
|
*/
|
|
|
|
struct DxvkSubmitEntry {
|
|
|
|
DxvkSubmitStatus* status;
|
|
|
|
DxvkSubmitInfo submit;
|
|
|
|
DxvkPresentInfo present;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-12-16 18:10:55 +01:00
|
|
|
/**
|
|
|
|
* \brief Submission queue
|
|
|
|
*/
|
|
|
|
class DxvkSubmissionQueue {
|
2019-05-05 14:08:07 +02:00
|
|
|
|
2017-12-16 18:10:55 +01:00
|
|
|
public:
|
|
|
|
|
|
|
|
DxvkSubmissionQueue(DxvkDevice* device);
|
|
|
|
~DxvkSubmissionQueue();
|
2018-06-04 23:24:42 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Number of pending submissions
|
|
|
|
*
|
|
|
|
* A return value of 0 indicates
|
|
|
|
* that the GPU is currently idle.
|
|
|
|
* \returns Pending submission count
|
|
|
|
*/
|
|
|
|
uint32_t pendingSubmissions() const {
|
2019-05-05 14:08:07 +02:00
|
|
|
return m_pending.load();
|
2018-06-04 23:24:42 +02:00
|
|
|
}
|
2019-07-18 22:52:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Retrieves estimated GPU idle time
|
|
|
|
*
|
|
|
|
* This is a monotonically increasing counter
|
|
|
|
* which can be evaluated periodically in order
|
|
|
|
* to calculate the GPU load.
|
|
|
|
* \returns Accumulated GPU idle time, in us
|
|
|
|
*/
|
|
|
|
uint64_t gpuIdleTicks() const {
|
|
|
|
return m_gpuIdle.load();
|
|
|
|
}
|
2019-09-22 18:51:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Retrieves last submission error
|
|
|
|
*
|
|
|
|
* In case an error occured during asynchronous command
|
|
|
|
* submission, it will be returned by this function.
|
|
|
|
* \returns Last error from command submission
|
|
|
|
*/
|
|
|
|
VkResult getLastError() const {
|
|
|
|
return m_lastError.load();
|
|
|
|
}
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2018-06-04 23:24:42 +02:00
|
|
|
/**
|
2019-05-05 14:08:07 +02:00
|
|
|
* \brief Submits a command list asynchronously
|
2018-06-04 23:24:42 +02:00
|
|
|
*
|
2019-05-05 14:08:07 +02:00
|
|
|
* Queues a command list for submission on the
|
|
|
|
* dedicated submission thread. Use this to take
|
|
|
|
* the submission overhead off the calling thread.
|
|
|
|
* \param [in] submitInfo Submission parameters
|
2018-06-04 23:24:42 +02:00
|
|
|
*/
|
2019-05-05 14:08:07 +02:00
|
|
|
void submit(
|
2019-07-05 14:27:45 +02:00
|
|
|
DxvkSubmitInfo submitInfo);
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
/**
|
|
|
|
* \brief Presents an image synchronously
|
|
|
|
*
|
|
|
|
* Waits for queued command lists to be submitted
|
|
|
|
* and then presents the current swap chain image
|
|
|
|
* of the presenter. May stall the calling thread.
|
|
|
|
* \param [in] present Present parameters
|
|
|
|
* \returns Status of the operation
|
|
|
|
*/
|
2019-07-05 14:27:45 +02:00
|
|
|
void present(
|
|
|
|
DxvkPresentInfo presentInfo,
|
|
|
|
DxvkSubmitStatus* status);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Synchronizes with one queue submission
|
|
|
|
*
|
|
|
|
* Waits for the result of the given submission
|
|
|
|
* or present operation to become available.
|
|
|
|
* \param [in,out] status Submission status
|
|
|
|
*/
|
|
|
|
void synchronizeSubmission(
|
|
|
|
DxvkSubmitStatus* status);
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
/**
|
|
|
|
* \brief Synchronizes with queue submissions
|
|
|
|
*
|
|
|
|
* Waits for all pending command lists to be
|
|
|
|
* submitted to the GPU before returning.
|
|
|
|
*/
|
|
|
|
void synchronize();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Locks device queue
|
|
|
|
*
|
|
|
|
* Locks the mutex that protects the Vulkan queue
|
|
|
|
* that DXVK uses for command buffer submission.
|
|
|
|
* This is needed when the app submits its own
|
|
|
|
* command buffers to the queue.
|
|
|
|
*/
|
|
|
|
void lockDeviceQueue();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Unlocks device queue
|
|
|
|
*
|
|
|
|
* Unlocks the mutex that protects the Vulkan
|
|
|
|
* queue used for command buffer submission.
|
|
|
|
*/
|
|
|
|
void unlockDeviceQueue();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2017-12-16 18:10:55 +01:00
|
|
|
DxvkDevice* m_device;
|
2019-09-22 18:51:11 +02:00
|
|
|
|
|
|
|
std::atomic<VkResult> m_lastError = { VK_SUCCESS };
|
2017-12-16 18:10:55 +01:00
|
|
|
|
|
|
|
std::atomic<bool> m_stopped = { false };
|
2019-05-05 14:08:07 +02:00
|
|
|
std::atomic<uint32_t> m_pending = { 0u };
|
2019-07-18 22:52:20 +02:00
|
|
|
std::atomic<uint64_t> m_gpuIdle = { 0ull };
|
2019-05-05 14:08:07 +02:00
|
|
|
|
2018-09-20 19:58:00 +02:00
|
|
|
std::mutex m_mutex;
|
2019-05-05 14:08:07 +02:00
|
|
|
std::mutex m_mutexQueue;
|
2017-12-16 18:10:55 +01:00
|
|
|
|
2019-05-05 14:08:07 +02:00
|
|
|
std::condition_variable m_appendCond;
|
|
|
|
std::condition_variable m_submitCond;
|
|
|
|
std::condition_variable m_finishCond;
|
|
|
|
|
2019-07-05 14:27:45 +02:00
|
|
|
std::queue<DxvkSubmitEntry> m_submitQueue;
|
|
|
|
std::queue<DxvkSubmitEntry> m_finishQueue;
|
2019-05-05 14:08:07 +02:00
|
|
|
|
|
|
|
dxvk::thread m_submitThread;
|
|
|
|
dxvk::thread m_finishThread;
|
|
|
|
|
|
|
|
VkResult submitToQueue(
|
|
|
|
const DxvkSubmitInfo& submission);
|
|
|
|
|
|
|
|
void submitCmdLists();
|
|
|
|
|
|
|
|
void finishCmdLists();
|
2017-12-16 18:10:55 +01:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-07-16 18:45:54 +02:00
|
|
|
}
|