1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-11 19:24:11 +01:00

[dxvk] Introduce single-use mode for CS chunks

This allows us to reset the CS chunk immediately while executing it,
which can reduce the overhead of the reset operation and may lead to
resources being released earlier.
This commit is contained in:
Philip Rebohle 2018-11-20 10:35:23 +01:00
parent e744117042
commit c61200d35f
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 63 additions and 17 deletions

View File

@ -3350,7 +3350,7 @@ namespace dxvk {
DxvkCsChunkRef D3D11DeviceContext::AllocCsChunk() {
return m_parent->AllocCsChunk();
return m_parent->AllocCsChunk(0);
}
}

View File

@ -333,8 +333,8 @@ namespace dxvk {
DXGI_FORMAT Format,
DXGI_VK_FORMAT_MODE Mode) const;
DxvkCsChunkRef AllocCsChunk() {
DxvkCsChunk* chunk = m_csChunkPool.allocChunk();
DxvkCsChunkRef AllocCsChunk(DxvkCsChunkFlags flags) {
DxvkCsChunk* chunk = m_csChunkPool.allocChunk(flags);
return DxvkCsChunkRef(chunk, &m_csChunkPool);
}

View File

@ -12,12 +12,32 @@ namespace dxvk {
}
void DxvkCsChunk::init(DxvkCsChunkFlags flags) {
m_flags = flags;
}
void DxvkCsChunk::executeAll(DxvkContext* ctx) {
auto cmd = m_head;
while (cmd != nullptr) {
cmd->exec(ctx);
cmd = cmd->next();
if (m_flags.test(DxvkCsChunkFlag::SingleUse)) {
m_commandCount = 0;
m_commandOffset = 0;
while (cmd != nullptr) {
auto next = cmd->next();
cmd->exec(ctx);
cmd->~DxvkCsCmd();
cmd = next;
}
m_head = nullptr;
m_tail = nullptr;
} else {
while (cmd != nullptr) {
cmd->exec(ctx);
cmd = cmd->next();
}
}
}
@ -25,15 +45,15 @@ namespace dxvk {
void DxvkCsChunk::reset() {
auto cmd = m_head;
m_commandCount = 0;
m_commandOffset = 0;
while (cmd != nullptr) {
auto next = cmd->next();
cmd->~DxvkCsCmd();
cmd = next;
}
m_commandCount = 0;
m_commandOffset = 0;
m_head = nullptr;
m_tail = nullptr;
}
@ -50,17 +70,22 @@ namespace dxvk {
}
DxvkCsChunk* DxvkCsChunkPool::allocChunk() {
DxvkCsChunk* DxvkCsChunkPool::allocChunk(DxvkCsChunkFlags flags) {
DxvkCsChunk* chunk = nullptr;
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
if (m_chunks.size() != 0) {
DxvkCsChunk* chunk = m_chunks.back();
chunk = m_chunks.back();
m_chunks.pop_back();
return chunk;
}
}
return new DxvkCsChunk();
if (!chunk)
chunk = new DxvkCsChunk();
chunk->init(flags);
return chunk;
}

View File

@ -82,6 +82,18 @@ namespace dxvk {
};
/**
* \brief Submission flags
*/
enum class DxvkCsChunkFlag : uint32_t {
/// Indicates that the submitted chunk will
/// no longer be needed after one submission.
SingleUse,
};
using DxvkCsChunkFlags = Flags<DxvkCsChunkFlag>;
/**
* \brief Command chunk
*
@ -103,7 +115,7 @@ namespace dxvk {
size_t commandCount() const {
return m_commandCount;
}
/**
* \brief Tries to add a command to the chunk
*
@ -136,6 +148,12 @@ namespace dxvk {
return true;
}
/**
* \brief Initializes chunk for recording
* \param [in] flags Chunk flags
*/
void init(DxvkCsChunkFlags flags);
/**
* \brief Executes all commands
*
@ -161,6 +179,8 @@ namespace dxvk {
DxvkCsCmd* m_head = nullptr;
DxvkCsCmd* m_tail = nullptr;
DxvkCsChunkFlags m_flags;
alignas(64)
char m_data[MaxBlockSize];
@ -190,9 +210,10 @@ namespace dxvk {
*
* Takes an existing chunk from the pool,
* or creates a new one if necessary.
* \param [in] flags Chunk flags
* \returns Allocated chunk object
*/
DxvkCsChunk* allocChunk();
DxvkCsChunk* allocChunk(DxvkCsChunkFlags flags);
/**
* \brief Releases a chunk
@ -288,8 +309,8 @@ namespace dxvk {
}
};
/**
* \brief Command stream thread
*