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

[dxvk] Optimize resource tracking

This way we only count each resource once per submission, or twice
in case a read access is followed by a write.

This also fixes a potential tracking bug with shader-writeable resources.
This commit is contained in:
Philip Rebohle 2024-10-30 03:54:32 +01:00
parent 10fac66007
commit bebabe8c38
4 changed files with 32 additions and 60 deletions

View File

@ -289,17 +289,20 @@ namespace dxvk {
*/
template<typename T>
void track(Rc<T>&& object, DxvkAccess access) {
m_objectTracker.track<DxvkResourceRef>(std::move(object), access, m_trackingId);
if (object->trackId(m_trackingId, access))
m_objectTracker.track<DxvkResourceRef>(std::move(object), access);
}
template<typename T>
void track(const Rc<T>& object, DxvkAccess access) {
m_objectTracker.track<DxvkResourceRef>(object.ptr(), access, m_trackingId);
if (object->trackId(m_trackingId, access))
m_objectTracker.track<DxvkResourceRef>(object.ptr(), access);
}
template<typename T>
void track(T* object, DxvkAccess access) {
m_objectTracker.track<DxvkResourceRef>(object, access, m_trackingId);
if (object->trackId(m_trackingId, access))
m_objectTracker.track<DxvkResourceRef>(object, access);
}
/**

View File

@ -5137,8 +5137,7 @@ namespace dxvk {
descriptorInfo.image.imageView = VK_NULL_HANDLE;
descriptorInfo.image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if (m_rcTracked.set(binding.resourceBinding))
m_cmd->track(res.sampler);
m_cmd->track(res.sampler);
} else {
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
descriptorInfo.image.imageView = VK_NULL_HANDLE;
@ -5159,8 +5158,7 @@ namespace dxvk {
descriptorInfo.image.imageView = viewHandle;
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
if (m_rcTracked.set(binding.resourceBinding))
m_cmd->track(res.imageView->image(), DxvkAccess::Read);
m_cmd->track(res.imageView->image(), DxvkAccess::Read);
} else {
descriptorInfo.image.sampler = VK_NULL_HANDLE;
descriptorInfo.image.imageView = VK_NULL_HANDLE;
@ -5181,10 +5179,8 @@ namespace dxvk {
descriptorInfo.image.imageView = viewHandle;
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->track(res.imageView->image(), (binding.access & vk::AccessWriteMask)
? DxvkAccess::Write : DxvkAccess::Read);
}
m_cmd->track(res.imageView->image(), (binding.access & vk::AccessWriteMask)
? DxvkAccess::Write : DxvkAccess::Read);
} else {
descriptorInfo.image.sampler = VK_NULL_HANDLE;
descriptorInfo.image.imageView = VK_NULL_HANDLE;
@ -5205,10 +5201,8 @@ namespace dxvk {
descriptorInfo.image.imageView = viewHandle;
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->track(res.sampler);
m_cmd->track(res.imageView->image(), DxvkAccess::Read);
}
m_cmd->track(res.sampler);
m_cmd->track(res.imageView->image(), DxvkAccess::Read);
} else {
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
descriptorInfo.image.imageView = VK_NULL_HANDLE;
@ -5222,8 +5216,7 @@ namespace dxvk {
if (res.bufferView != nullptr) {
descriptorInfo.texelBuffer = res.bufferView->handle();
if (m_rcTracked.set(binding.resourceBinding))
m_cmd->track(res.bufferView->buffer(), DxvkAccess::Read);
m_cmd->track(res.bufferView->buffer(), DxvkAccess::Read);
} else {
descriptorInfo.texelBuffer = VK_NULL_HANDLE;
}
@ -5235,10 +5228,8 @@ namespace dxvk {
if (res.bufferView != nullptr) {
descriptorInfo.texelBuffer = res.bufferView->handle();
if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->track(res.bufferView->buffer(), (binding.access & vk::AccessWriteMask)
? DxvkAccess::Write : DxvkAccess::Read);
}
m_cmd->track(res.bufferView->buffer(), (binding.access & vk::AccessWriteMask)
? DxvkAccess::Write : DxvkAccess::Read);
} else {
descriptorInfo.texelBuffer = VK_NULL_HANDLE;
}
@ -5250,8 +5241,7 @@ namespace dxvk {
if (res.bufferSlice.length()) {
descriptorInfo = res.bufferSlice.getDescriptor();
if (m_rcTracked.set(binding.resourceBinding))
m_cmd->track(res.bufferSlice.buffer(), DxvkAccess::Read);
m_cmd->track(res.bufferSlice.buffer(), DxvkAccess::Read);
} else {
descriptorInfo.buffer.buffer = VK_NULL_HANDLE;
descriptorInfo.buffer.offset = 0;
@ -5265,10 +5255,8 @@ namespace dxvk {
if (res.bufferSlice.length()) {
descriptorInfo = res.bufferSlice.getDescriptor();
if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->track(res.bufferSlice.buffer(), (binding.access & vk::AccessWriteMask)
? DxvkAccess::Write : DxvkAccess::Read);
}
m_cmd->track(res.bufferSlice.buffer(), (binding.access & vk::AccessWriteMask)
? DxvkAccess::Write : DxvkAccess::Read);
} else {
descriptorInfo.buffer.buffer = VK_NULL_HANDLE;
descriptorInfo.buffer.offset = 0;
@ -5552,9 +5540,7 @@ namespace dxvk {
m_state.vi.indexType);
}
if (m_vbTracked.set(MaxNumVertexBindings))
m_cmd->track(m_state.vi.indexBuffer.buffer(), DxvkAccess::Read);
m_cmd->track(m_state.vi.indexBuffer.buffer(), DxvkAccess::Read);
return true;
}
@ -5591,8 +5577,7 @@ namespace dxvk {
newDynamicStrides &= strides[i] >= m_state.vi.vertexExtents[i];
}
if (m_vbTracked.set(binding))
m_cmd->track(m_state.vi.vertexBuffers[binding].buffer(), DxvkAccess::Read);
m_cmd->track(m_state.vi.vertexBuffers[binding].buffer(), DxvkAccess::Read);
} else {
buffers[i] = VK_NULL_HANDLE;
offsets[i] = 0;
@ -6669,10 +6654,6 @@ namespace dxvk {
void DxvkContext::beginCurrentCommands() {
// Mark all resources as untracked
m_vbTracked.clear();
m_rcTracked.clear();
// The current state of the internal command buffer is
// undefined, so we have to bind and set up everything
// before any draw or dispatch command is recorded.

View File

@ -177,9 +177,6 @@ namespace dxvk {
void bindIndexBuffer(
DxvkBufferSlice&& buffer,
VkIndexType indexType) {
if (!m_state.vi.indexBuffer.matchesBuffer(buffer))
m_vbTracked.clr(MaxNumVertexBindings);
m_state.vi.indexBuffer = std::move(buffer);
m_state.vi.indexType = indexType;
@ -218,11 +215,6 @@ namespace dxvk {
VkShaderStageFlags stages,
uint32_t slot,
DxvkBufferSlice&& buffer) {
bool needsUpdate = !m_rc[slot].bufferSlice.matchesBuffer(buffer);
if (likely(needsUpdate))
m_rcTracked.clr(slot);
m_rc[slot].bufferSlice = std::move(buffer);
m_descriptorState.dirtyBuffers(stages);
@ -261,7 +253,6 @@ namespace dxvk {
}
m_rc[slot].imageView = std::move(view);
m_rcTracked.clr(slot);
m_descriptorState.dirtyViews(stages);
}
@ -288,8 +279,6 @@ namespace dxvk {
m_rc[slot].bufferView = nullptr;
}
m_rcTracked.clr(slot);
m_descriptorState.dirtyViews(stages);
}
@ -307,7 +296,6 @@ namespace dxvk {
uint32_t slot,
Rc<DxvkSampler>&& sampler) {
m_rc[slot].sampler = std::move(sampler);
m_rcTracked.clr(slot);
m_descriptorState.dirtyViews(stages);
}
@ -371,9 +359,6 @@ namespace dxvk {
uint32_t binding,
DxvkBufferSlice&& buffer,
uint32_t stride) {
if (!m_state.vi.vertexBuffers[binding].matchesBuffer(buffer))
m_vbTracked.clr(binding);
m_state.vi.vertexBuffers[binding] = std::move(buffer);
m_state.vi.vertexStrides[binding] = stride;
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
@ -1413,9 +1398,6 @@ namespace dxvk {
DxvkRenderTargetLayouts m_rtLayouts = { };
DxvkBindingSet<MaxNumVertexBindings + 1> m_vbTracked;
DxvkBindingSet<MaxNumResourceSlots> m_rcTracked;
std::vector<DxvkDeferredClear> m_deferredClears;
std::vector<VkWriteDescriptorSet> m_descriptorWrites;

View File

@ -542,10 +542,18 @@ namespace dxvk {
* command list and optimize certain transfer operations.
* \param [in] trackingId Tracking ID
* \param [in] access Tracked access
* \returns \c true if the tracking ID was updated, or \c false
* if the resource was already tracked with the same ID.
*/
void trackId(uint64_t trackingId, DxvkAccess access) {
bool trackId(uint64_t trackingId, DxvkAccess access) {
// Encode write access in the least significant bit
m_trackId = std::max(m_trackId, (trackingId << 1u) + uint64_t(access == DxvkAccess::Write));
uint64_t trackId = (trackingId << 1u) + uint64_t(access == DxvkAccess::Write);
if (trackId <= m_trackId)
return false;
m_trackId = trackId;
return true;
}
/**
@ -623,15 +631,13 @@ namespace dxvk {
public:
template<typename T>
explicit DxvkResourceRef(Rc<T>&& object, DxvkAccess access, uint64_t trackingId)
explicit DxvkResourceRef(Rc<T>&& object, DxvkAccess access)
: m_ptr(reinterpret_cast<uintptr_t>(static_cast<DxvkPagedResource*>(object.ptr())) | uintptr_t(access)) {
object->trackId(trackingId, access);
object.unsafeExtract()->convertRef(DxvkAccess::None, access);
}
explicit DxvkResourceRef(DxvkPagedResource* object, DxvkAccess access, uint64_t trackingId)
explicit DxvkResourceRef(DxvkPagedResource* object, DxvkAccess access)
: m_ptr(reinterpret_cast<uintptr_t>(object) | uintptr_t(access)) {
object->trackId(trackingId, access);
object->acquire(access);
}