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:
parent
10fac66007
commit
bebabe8c38
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user