mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[dxvk] Rework queue submission helper
We want this to be less verbose and smarter about when to perform submissions for when we introduce the ability to split a command list into multiple submissions.
This commit is contained in:
parent
f88239719c
commit
d367fac64e
@ -2,7 +2,91 @@
|
||||
#include "dxvk_device.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
|
||||
DxvkCommandSubmission::DxvkCommandSubmission() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkCommandSubmission::~DxvkCommandSubmission() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandSubmission::waitSemaphore(
|
||||
VkSemaphore semaphore,
|
||||
uint64_t value,
|
||||
VkPipelineStageFlags2 stageMask) {
|
||||
VkSemaphoreSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
submitInfo.semaphore = semaphore;
|
||||
submitInfo.value = value;
|
||||
submitInfo.stageMask = stageMask;
|
||||
|
||||
m_semaphoreWaits.push_back(submitInfo);
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandSubmission::signalSemaphore(
|
||||
VkSemaphore semaphore,
|
||||
uint64_t value,
|
||||
VkPipelineStageFlags2 stageMask) {
|
||||
VkSemaphoreSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
submitInfo.semaphore = semaphore;
|
||||
submitInfo.value = value;
|
||||
submitInfo.stageMask = stageMask;
|
||||
|
||||
m_semaphoreSignals.push_back(submitInfo);
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandSubmission::executeCommandBuffer(
|
||||
VkCommandBuffer commandBuffer) {
|
||||
VkCommandBufferSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
||||
submitInfo.commandBuffer = commandBuffer;
|
||||
|
||||
m_commandBuffers.push_back(submitInfo);
|
||||
}
|
||||
|
||||
|
||||
VkResult DxvkCommandSubmission::submit(
|
||||
DxvkDevice* device,
|
||||
VkQueue queue) {
|
||||
auto vk = device->vkd();
|
||||
|
||||
VkSubmitInfo2 submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO_2 };
|
||||
|
||||
if (!m_semaphoreWaits.empty()) {
|
||||
submitInfo.waitSemaphoreInfoCount = m_semaphoreWaits.size();
|
||||
submitInfo.pWaitSemaphoreInfos = m_semaphoreWaits.data();
|
||||
}
|
||||
|
||||
if (!m_commandBuffers.empty()) {
|
||||
submitInfo.commandBufferInfoCount = m_commandBuffers.size();
|
||||
submitInfo.pCommandBufferInfos = m_commandBuffers.data();
|
||||
}
|
||||
|
||||
if (!m_semaphoreSignals.empty()) {
|
||||
submitInfo.signalSemaphoreInfoCount = m_semaphoreSignals.size();
|
||||
submitInfo.pSignalSemaphoreInfos = m_semaphoreSignals.data();
|
||||
}
|
||||
|
||||
VkResult vr = VK_SUCCESS;
|
||||
|
||||
if (submitInfo.waitSemaphoreInfoCount || submitInfo.commandBufferInfoCount || submitInfo.signalSemaphoreInfoCount)
|
||||
vr = vk->vkQueueSubmit2(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
|
||||
this->reset();
|
||||
return vr;
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandSubmission::reset() {
|
||||
m_semaphoreWaits.clear();
|
||||
m_semaphoreSignals.clear();
|
||||
m_commandBuffers.clear();
|
||||
}
|
||||
|
||||
|
||||
DxvkCommandList::DxvkCommandList(DxvkDevice* device)
|
||||
: m_device (device),
|
||||
m_vkd (device->vkd()),
|
||||
@ -12,7 +96,9 @@ namespace dxvk {
|
||||
const auto& transferQueue = m_device->queues().transfer;
|
||||
|
||||
VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
|
||||
m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore);
|
||||
|
||||
if (m_vkd->vkCreateSemaphore(m_vkd->device(), &semaphoreInfo, nullptr, &m_sdmaSemaphore))
|
||||
throw DxvkError("DxvkCommandList: Failed to create semaphore");
|
||||
|
||||
VkCommandPoolCreateInfo poolInfo;
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
@ -64,86 +150,58 @@ namespace dxvk {
|
||||
VkResult DxvkCommandList::submit(
|
||||
VkSemaphore semaphore,
|
||||
uint64_t& semaphoreValue) {
|
||||
VkResult status = VK_SUCCESS;
|
||||
|
||||
const auto& graphics = m_device->queues().graphics;
|
||||
const auto& transfer = m_device->queues().transfer;
|
||||
|
||||
m_submission.reset();
|
||||
m_commandSubmission.reset();
|
||||
|
||||
if (m_cmdBuffersUsed.test(DxvkCmdBuffer::SdmaBuffer)) {
|
||||
VkCommandBufferSubmitInfo cmdInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
||||
cmdInfo.commandBuffer = m_sdmaBuffer;
|
||||
m_submission.cmdBuffers.push_back(cmdInfo);
|
||||
m_commandSubmission.executeCommandBuffer(m_sdmaBuffer);
|
||||
|
||||
if (m_device->hasDedicatedTransferQueue()) {
|
||||
VkSemaphoreSubmitInfo signalInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
signalInfo.semaphore = m_sdmaSemaphore;
|
||||
signalInfo.stageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
|
||||
m_submission.signalInfos.push_back(signalInfo);
|
||||
m_commandSubmission.signalSemaphore(m_sdmaSemaphore, 0, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
|
||||
|
||||
VkResult status = submitToQueue(transfer.queueHandle, m_submission);
|
||||
|
||||
if (status != VK_SUCCESS)
|
||||
if ((status = m_commandSubmission.submit(m_device, transfer.queueHandle)))
|
||||
return status;
|
||||
|
||||
m_submission.reset();
|
||||
|
||||
VkSemaphoreSubmitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
waitInfo.semaphore = m_sdmaSemaphore;
|
||||
waitInfo.stageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
|
||||
m_submission.waitInfos.push_back(waitInfo);
|
||||
m_commandSubmission.waitSemaphore(m_sdmaSemaphore, 0, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_cmdBuffersUsed.test(DxvkCmdBuffer::InitBuffer)) {
|
||||
VkCommandBufferSubmitInfo cmdInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
||||
cmdInfo.commandBuffer = m_initBuffer;
|
||||
m_submission.cmdBuffers.push_back(cmdInfo);
|
||||
}
|
||||
if (m_cmdBuffersUsed.test(DxvkCmdBuffer::InitBuffer))
|
||||
m_commandSubmission.executeCommandBuffer(m_initBuffer);
|
||||
|
||||
if (m_cmdBuffersUsed.test(DxvkCmdBuffer::ExecBuffer))
|
||||
m_commandSubmission.executeCommandBuffer(m_execBuffer);
|
||||
|
||||
if (m_cmdBuffersUsed.test(DxvkCmdBuffer::ExecBuffer)) {
|
||||
VkCommandBufferSubmitInfo cmdInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO };
|
||||
cmdInfo.commandBuffer = m_execBuffer;
|
||||
m_submission.cmdBuffers.push_back(cmdInfo);
|
||||
}
|
||||
|
||||
if (m_wsiSemaphores.acquire) {
|
||||
VkSemaphoreSubmitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
waitInfo.semaphore = m_wsiSemaphores.acquire;
|
||||
waitInfo.stageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
|
||||
m_submission.waitInfos.push_back(waitInfo);
|
||||
m_commandSubmission.waitSemaphore(m_wsiSemaphores.acquire,
|
||||
0, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT);
|
||||
}
|
||||
|
||||
if (m_wsiSemaphores.present) {
|
||||
VkSemaphoreSubmitInfo signalInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
signalInfo.semaphore = m_wsiSemaphores.present;
|
||||
signalInfo.stageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
|
||||
m_submission.signalInfos.push_back(signalInfo);
|
||||
m_commandSubmission.signalSemaphore(m_wsiSemaphores.present,
|
||||
0, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
|
||||
}
|
||||
|
||||
|
||||
for (const auto& entry : m_waitSemaphores) {
|
||||
VkSemaphoreSubmitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
waitInfo.semaphore = entry.fence->handle();
|
||||
waitInfo.value = entry.value;
|
||||
waitInfo.stageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
|
||||
m_submission.waitInfos.push_back(waitInfo);
|
||||
m_commandSubmission.waitSemaphore(
|
||||
entry.fence->handle(),
|
||||
entry.value, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT);
|
||||
}
|
||||
|
||||
for (const auto& entry : m_signalSemaphores) {
|
||||
VkSemaphoreSubmitInfo signalInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
signalInfo.semaphore = entry.fence->handle();
|
||||
signalInfo.value = entry.value;
|
||||
signalInfo.stageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
|
||||
m_submission.signalInfos.push_back(signalInfo);
|
||||
}
|
||||
for (const auto& entry : m_signalSemaphores)
|
||||
m_commandSubmission.signalSemaphore(entry.fence->handle(), entry.value, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
|
||||
|
||||
// Signal global timeline semaphore
|
||||
VkSemaphoreSubmitInfo signalInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO };
|
||||
signalInfo.semaphore = semaphore;
|
||||
signalInfo.value = ++semaphoreValue;
|
||||
signalInfo.stageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
|
||||
m_submission.signalInfos.push_back(signalInfo);
|
||||
m_commandSubmission.signalSemaphore(semaphore,
|
||||
++semaphoreValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT);
|
||||
|
||||
return submitToQueue(graphics.queueHandle, m_submission);
|
||||
if ((status = m_commandSubmission.submit(m_device, graphics.queueHandle)))
|
||||
return status;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -211,19 +269,4 @@ namespace dxvk {
|
||||
m_wsiSemaphores = vk::PresenterSync();
|
||||
}
|
||||
|
||||
|
||||
VkResult DxvkCommandList::submitToQueue(
|
||||
VkQueue queue,
|
||||
const DxvkQueueSubmission& info) {
|
||||
VkSubmitInfo2 submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO_2 };
|
||||
submitInfo.waitSemaphoreInfoCount = info.waitInfos.size();
|
||||
submitInfo.pWaitSemaphoreInfos = info.waitInfos.data();
|
||||
submitInfo.commandBufferInfoCount = info.cmdBuffers.size();
|
||||
submitInfo.pCommandBufferInfos = info.cmdBuffers.data();
|
||||
submitInfo.signalSemaphoreInfoCount = info.signalInfos.size();
|
||||
submitInfo.pSignalSemaphoreInfos = info.signalInfos.data();
|
||||
|
||||
return m_vkd->vkQueueSubmit2(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,22 +35,71 @@ namespace dxvk {
|
||||
using DxvkCmdBufferFlags = Flags<DxvkCmdBuffer>;
|
||||
|
||||
/**
|
||||
* \brief Queue submission info
|
||||
* \brief Queue command submission
|
||||
*
|
||||
* Convenience struct that holds data for
|
||||
* actual command submissions. Internal use
|
||||
* only, array sizes are based on need.
|
||||
* Convenience class that holds data for a single
|
||||
* command submission, which then easily be executed.
|
||||
*/
|
||||
struct DxvkQueueSubmission {
|
||||
std::vector<VkSemaphoreSubmitInfo> waitInfos;
|
||||
std::vector<VkSemaphoreSubmitInfo> signalInfos;
|
||||
std::vector<VkCommandBufferSubmitInfo> cmdBuffers;
|
||||
class DxvkCommandSubmission {
|
||||
|
||||
public:
|
||||
|
||||
DxvkCommandSubmission();
|
||||
~DxvkCommandSubmission();
|
||||
|
||||
/**
|
||||
* \brief Adds a semaphore to wait on
|
||||
*
|
||||
* \param [in] semaphore The semaphore
|
||||
* \param [in] value Semaphore value
|
||||
* \param [in] stageMask Stages to block
|
||||
*/
|
||||
void waitSemaphore(
|
||||
VkSemaphore semaphore,
|
||||
uint64_t value,
|
||||
VkPipelineStageFlags2 stageMask);
|
||||
|
||||
/**
|
||||
* \brief Adds a semaphore to signal
|
||||
*
|
||||
* \param [in] semaphore The semaphore
|
||||
* \param [in] value Semaphore value
|
||||
* \param [in] stageMask Stages to signal on
|
||||
*/
|
||||
void signalSemaphore(
|
||||
VkSemaphore semaphore,
|
||||
uint64_t value,
|
||||
VkPipelineStageFlags2 stageMask);
|
||||
|
||||
/**
|
||||
* \brief Adds a command buffer to execute
|
||||
* \param [in] commandBuffer The command buffer
|
||||
*/
|
||||
void executeCommandBuffer(
|
||||
VkCommandBuffer commandBuffer);
|
||||
|
||||
/**
|
||||
* \brief Executes submission and resets object
|
||||
*
|
||||
* \param [in] device DXVK device
|
||||
* \param [in] queue Queue to submit to
|
||||
* \returns Submission return value
|
||||
*/
|
||||
VkResult submit(
|
||||
DxvkDevice* device,
|
||||
VkQueue queue);
|
||||
|
||||
/**
|
||||
* \brief Resets object
|
||||
*/
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<VkSemaphoreSubmitInfo> m_semaphoreWaits;
|
||||
std::vector<VkSemaphoreSubmitInfo> m_semaphoreSignals;
|
||||
std::vector<VkCommandBufferSubmitInfo> m_commandBuffers;
|
||||
|
||||
void reset() {
|
||||
waitInfos.clear();
|
||||
signalInfos.clear();
|
||||
cmdBuffers.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -862,7 +911,8 @@ namespace dxvk {
|
||||
DxvkGpuQueryTracker m_gpuQueryTracker;
|
||||
DxvkBufferTracker m_bufferTracker;
|
||||
DxvkStatCounters m_statCounters;
|
||||
DxvkQueueSubmission m_submission;
|
||||
|
||||
DxvkCommandSubmission m_commandSubmission;
|
||||
|
||||
std::vector<DxvkFenceValuePair> m_waitSemaphores;
|
||||
std::vector<DxvkFenceValuePair> m_signalSemaphores;
|
||||
@ -879,10 +929,6 @@ namespace dxvk {
|
||||
if (cmdBuffer == DxvkCmdBuffer::SdmaBuffer) return m_sdmaBuffer;
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkResult submitToQueue(
|
||||
VkQueue queue,
|
||||
const DxvkQueueSubmission& info);
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user