Skip to content

Commit

Permalink
wip barrier atomic store stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
doitsujin committed Feb 15, 2025
1 parent d904c3b commit 962f838
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 82 deletions.
45 changes: 37 additions & 8 deletions src/dxvk/dxvk_barrier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,36 @@ namespace dxvk {

bool DxvkBarrierTracker::findRange(
const DxvkAddressRange& range,
DxvkAccess accessType) const {
DxvkAccess accessType,
DxvkAtomicStore storeOp) const {
uint32_t rootIndex = computeRootIndex(range, accessType);
return findNode(range, rootIndex);
uint32_t nodeIndex = findNode(range, rootIndex);

if (!nodeIndex || !storeOp)
return nodeIndex;

// If we are checking for a specific order-invariant store
// op, report a hazard if either the found range does not
// cover the entire range to look up, or if the store op
// does not match previous stores.
auto& node = m_nodes[nodeIndex];

return node.payload.storeOp != storeOp
|| !node.addressRange.contains(range);
}


void DxvkBarrierTracker::insertRange(
const DxvkAddressRange& range,
DxvkAccess accessType) {
uint32_t rootIndex = computeRootIndex(range, accessType);
DxvkAccess accessType,
DxvkAtomicStore storeOp) {
DxvkBarrierPayload payload = { };
payload.storeOp = storeOp;

// If we can just insert the node with no conflicts,
// we don't have to do anything.
uint32_t nodeIndex = insertNode(range, rootIndex);
uint32_t rootIndex = computeRootIndex(range, accessType);
uint32_t nodeIndex = insertNode(range, rootIndex, payload);

if (likely(!nodeIndex))
return;
Expand All @@ -42,6 +58,9 @@ namespace dxvk {
// range we want to add already, also don't do anything.
auto& node = m_nodes[nodeIndex];

if (node.payload.storeOp != payload.storeOp)
node.payload.storeOp = DxvkAtomicStore::None;

if (node.addressRange.contains(range))
return;

Expand Down Expand Up @@ -82,12 +101,15 @@ namespace dxvk {
mergedRange.rangeStart = std::min(mergedRange.rangeStart, node.addressRange.rangeStart);
mergedRange.rangeEnd = std::max(mergedRange.rangeEnd, node.addressRange.rangeEnd);

if (node.payload.storeOp != payload.storeOp)
payload.storeOp = DxvkAtomicStore::None;

removeNode(nodeIndex, rootIndex);

nodeIndex = findNode(range, rootIndex);
}

insertNode(mergedRange, rootIndex);
insertNode(mergedRange, rootIndex, payload);
}


Expand Down Expand Up @@ -166,7 +188,8 @@ namespace dxvk {

uint32_t DxvkBarrierTracker::insertNode(
const DxvkAddressRange& range,
uint32_t rootIndex) {
uint32_t rootIndex,
DxvkBarrierPayload payload) {
// Check if the given root is valid at all
uint64_t rootBit = uint64_t(1u) << (rootIndex - 1u);

Expand All @@ -178,6 +201,7 @@ namespace dxvk {
auto& node = m_nodes[rootIndex];
node.header = 0;
node.addressRange = range;
node.payload = payload;
return 0;
} else {
// Traverse tree and abort if we find any range
Expand Down Expand Up @@ -209,6 +233,7 @@ namespace dxvk {
node.setRed(true);
node.setParent(parentIndex);
node.addressRange = range;
node.payload = payload;

// Only do the fixup to maintain red-black properties if
// we haven't marked the root node as red in a deletion.
Expand Down Expand Up @@ -238,6 +263,7 @@ namespace dxvk {
childIndex = m_nodes[childIndex].child(0);

node.addressRange = m_nodes[childIndex].addressRange;
node.payload = m_nodes[childIndex].payload;
removeNode(childIndex, rootIndex);
} else {
// Deletion is expected to be exceptionally rare, to the point of
Expand Down Expand Up @@ -268,6 +294,7 @@ namespace dxvk {
node.setRed(child.isRed());

node.addressRange = child.addressRange;
node.payload = child.payload;

if (cl) m_nodes[cl].setParent(nodeIndex);
if (cr) m_nodes[cr].setParent(nodeIndex);
Expand Down Expand Up @@ -378,6 +405,7 @@ namespace dxvk {
node.setChild(1, rr);

std::swap(node.addressRange, m_nodes[r].addressRange);
std::swap(node.payload, m_nodes[r].payload);
}


Expand Down Expand Up @@ -406,6 +434,7 @@ namespace dxvk {
node.setChild(1, l);

std::swap(node.addressRange, m_nodes[l].addressRange);
std::swap(node.payload, m_nodes[l].payload);
}


Expand Down Expand Up @@ -498,4 +527,4 @@ namespace dxvk {
flush(list);
}

}
}
24 changes: 20 additions & 4 deletions src/dxvk/dxvk_barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ namespace dxvk {
};


/**
* \brief Barrier nodepayload
*/
struct DxvkBarrierPayload {
DxvkAtomicStore storeOp = DxvkAtomicStore::None;
};


/**
* \brief Barrier tree node
*
Expand All @@ -62,6 +70,9 @@ namespace dxvk {
// Address range of the node
DxvkAddressRange addressRange = { };

// Node payload
DxvkBarrierPayload payload = { };

void setRed(bool red) {
header &= ~uint64_t(1u);
header |= uint64_t(red);
Expand Down Expand Up @@ -117,21 +128,25 @@ namespace dxvk {
*
* \param [in] range Resource range
* \param [in] accessType Access type
* \param [in] storeOp Invariant store op
* \returns \c true if the range has a pending access
*/
bool findRange(
const DxvkAddressRange& range,
DxvkAccess accessType) const;
DxvkAccess accessType,
DxvkAtomicStore storeOp) const;

/**
* \brief Inserts address range for a given access type
*
* \param [in] range Resource range
* \param [in] accessType Access type
* \param [in] storeOp Invariant store op
*/
void insertRange(
const DxvkAddressRange& range,
DxvkAccess accessType);
DxvkAccess accessType,
DxvkAtomicStore storeOp);

/**
* \brief Clears the entire structure
Expand Down Expand Up @@ -166,7 +181,8 @@ namespace dxvk {

uint32_t insertNode(
const DxvkAddressRange& range,
uint32_t rootIndex);
uint32_t rootIndex,
DxvkBarrierPayload payload);

void removeNode(
uint32_t nodeIndex,
Expand Down Expand Up @@ -285,4 +301,4 @@ namespace dxvk {

};

}
}
Loading

0 comments on commit 962f838

Please sign in to comment.