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

[dxvk] Use linked list for CS chunks

Improves memory efficiency and CPU overhead of the CSMT implementation
when the average number of bytes per command entry is less than 64 bytes.
This commit is contained in:
Philip Rebohle 2018-03-02 10:31:08 +01:00
parent 3dea58dabc
commit e0fbfdf0e2
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 53 additions and 13 deletions

View File

@ -8,19 +8,31 @@ namespace dxvk {
DxvkCsChunk::~DxvkCsChunk() { DxvkCsChunk::~DxvkCsChunk() {
for (size_t i = 0; i < m_commandCount; i++) auto cmd = m_head;
m_commandList[i]->~DxvkCsCmd();
while (cmd != nullptr) {
auto next = cmd->next();
cmd->~DxvkCsCmd();
cmd = next;
}
} }
void DxvkCsChunk::executeAll(DxvkContext* ctx) { void DxvkCsChunk::executeAll(DxvkContext* ctx) {
for (size_t i = 0; i < m_commandCount; i++) { auto cmd = m_head;
m_commandList[i]->exec(ctx);
m_commandList[i]->~DxvkCsCmd(); while (cmd != nullptr) {
auto next = cmd->next();
cmd->exec(ctx);
cmd->~DxvkCsCmd();
cmd = next;
} }
m_commandCount = 0; m_commandCount = 0;
m_commandOffset = 0; m_commandOffset = 0;
m_head = nullptr;
m_tail = nullptr;
} }

View File

@ -22,12 +22,35 @@ namespace dxvk {
virtual ~DxvkCsCmd() { } virtual ~DxvkCsCmd() { }
/**
* \brief Retrieves next command in a command chain
*
* This can be used to quickly iterate
* over commands within a chunk.
* \returns Pointer the next command
*/
DxvkCsCmd* next() const {
return m_next;
}
/**
* \brief Sets next command in a command chain
* \param [in] next Next command
*/
void setNext(DxvkCsCmd* next) {
m_next = next;
}
/** /**
* \brief Executes embedded commands * \brief Executes embedded commands
* \param [in] ctx The target context * \param [in] ctx The target context
*/ */
virtual void exec(DxvkContext* ctx) const = 0; virtual void exec(DxvkContext* ctx) const = 0;
private:
DxvkCsCmd* m_next = nullptr;
}; };
@ -65,8 +88,7 @@ namespace dxvk {
* Stores a list of commands. * Stores a list of commands.
*/ */
class DxvkCsChunk : public RcObject { class DxvkCsChunk : public RcObject {
constexpr static size_t MaxCommands = 1024; constexpr static size_t MaxBlockSize = 65536;
constexpr static size_t MaxBlockSize = 64 * MaxCommands;
public: public:
DxvkCsChunk(); DxvkCsChunk();
@ -96,13 +118,18 @@ namespace dxvk {
bool push(T& command) { bool push(T& command) {
using FuncType = DxvkCsTypedCmd<T>; using FuncType = DxvkCsTypedCmd<T>;
if (m_commandCount >= MaxCommands if (m_commandOffset + sizeof(FuncType) > MaxBlockSize)
|| m_commandOffset + sizeof(FuncType) > MaxBlockSize)
return false; return false;
m_commandList[m_commandCount] = DxvkCsCmd* tail = m_tail;
new (m_data + m_commandOffset)
FuncType(std::move(command)); m_tail = new (m_data + m_commandOffset)
FuncType(std::move(command));
if (tail != nullptr)
tail->setNext(m_tail);
else
m_head = m_tail;
m_commandCount += 1; m_commandCount += 1;
m_commandOffset += sizeof(FuncType); m_commandOffset += sizeof(FuncType);
@ -123,7 +150,8 @@ namespace dxvk {
size_t m_commandCount = 0; size_t m_commandCount = 0;
size_t m_commandOffset = 0; size_t m_commandOffset = 0;
std::array<DxvkCsCmd*, MaxCommands> m_commandList; DxvkCsCmd* m_head = nullptr;
DxvkCsCmd* m_tail = nullptr;
alignas(64) alignas(64)
char m_data[MaxBlockSize]; char m_data[MaxBlockSize];