mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-22 07:54:15 +01:00
[dxvk] Introduce tracking ID for resource tracking
Replaces the existing bit masks, which is possible now because the CS thread is the only place where submissions happen now. 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
0e14fff749
@ -289,17 +289,20 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void track(Rc<T>&& object, DxvkAccess access) {
|
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>
|
template<typename T>
|
||||||
void track(const Rc<T>& object, DxvkAccess access) {
|
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>
|
template<typename T>
|
||||||
void track(T* object, DxvkAccess access) {
|
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.imageView = VK_NULL_HANDLE;
|
||||||
descriptorInfo.image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
descriptorInfo.image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
if (m_rcTracked.set(binding.resourceBinding))
|
m_cmd->track(res.sampler);
|
||||||
m_cmd->track(res.sampler);
|
|
||||||
} else {
|
} else {
|
||||||
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
|
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
|
||||||
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
||||||
@ -5159,8 +5158,7 @@ namespace dxvk {
|
|||||||
descriptorInfo.image.imageView = viewHandle;
|
descriptorInfo.image.imageView = viewHandle;
|
||||||
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
|
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 {
|
} else {
|
||||||
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
||||||
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
||||||
@ -5181,10 +5179,8 @@ namespace dxvk {
|
|||||||
descriptorInfo.image.imageView = viewHandle;
|
descriptorInfo.image.imageView = viewHandle;
|
||||||
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
|
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
|
||||||
|
|
||||||
if (m_rcTracked.set(binding.resourceBinding)) {
|
m_cmd->track(res.imageView->image(), (binding.access & vk::AccessWriteMask)
|
||||||
m_cmd->track(res.imageView->image(), (binding.access & vk::AccessWriteMask)
|
? DxvkAccess::Write : DxvkAccess::Read);
|
||||||
? DxvkAccess::Write : DxvkAccess::Read);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
descriptorInfo.image.sampler = VK_NULL_HANDLE;
|
||||||
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
||||||
@ -5205,10 +5201,8 @@ namespace dxvk {
|
|||||||
descriptorInfo.image.imageView = viewHandle;
|
descriptorInfo.image.imageView = viewHandle;
|
||||||
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
|
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;
|
||||||
|
|
||||||
if (m_rcTracked.set(binding.resourceBinding)) {
|
m_cmd->track(res.sampler);
|
||||||
m_cmd->track(res.sampler);
|
m_cmd->track(res.imageView->image(), DxvkAccess::Read);
|
||||||
m_cmd->track(res.imageView->image(), DxvkAccess::Read);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
|
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
|
||||||
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
descriptorInfo.image.imageView = VK_NULL_HANDLE;
|
||||||
@ -5222,8 +5216,7 @@ namespace dxvk {
|
|||||||
if (res.bufferView != nullptr) {
|
if (res.bufferView != nullptr) {
|
||||||
descriptorInfo.texelBuffer = res.bufferView->handle();
|
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 {
|
} else {
|
||||||
descriptorInfo.texelBuffer = VK_NULL_HANDLE;
|
descriptorInfo.texelBuffer = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
@ -5235,10 +5228,8 @@ namespace dxvk {
|
|||||||
if (res.bufferView != nullptr) {
|
if (res.bufferView != nullptr) {
|
||||||
descriptorInfo.texelBuffer = res.bufferView->handle();
|
descriptorInfo.texelBuffer = res.bufferView->handle();
|
||||||
|
|
||||||
if (m_rcTracked.set(binding.resourceBinding)) {
|
m_cmd->track(res.bufferView->buffer(), (binding.access & vk::AccessWriteMask)
|
||||||
m_cmd->track(res.bufferView->buffer(), (binding.access & vk::AccessWriteMask)
|
? DxvkAccess::Write : DxvkAccess::Read);
|
||||||
? DxvkAccess::Write : DxvkAccess::Read);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
descriptorInfo.texelBuffer = VK_NULL_HANDLE;
|
descriptorInfo.texelBuffer = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
@ -5250,8 +5241,7 @@ namespace dxvk {
|
|||||||
if (res.bufferSlice.length()) {
|
if (res.bufferSlice.length()) {
|
||||||
descriptorInfo = res.bufferSlice.getDescriptor();
|
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 {
|
} else {
|
||||||
descriptorInfo.buffer.buffer = VK_NULL_HANDLE;
|
descriptorInfo.buffer.buffer = VK_NULL_HANDLE;
|
||||||
descriptorInfo.buffer.offset = 0;
|
descriptorInfo.buffer.offset = 0;
|
||||||
@ -5265,10 +5255,8 @@ namespace dxvk {
|
|||||||
if (res.bufferSlice.length()) {
|
if (res.bufferSlice.length()) {
|
||||||
descriptorInfo = res.bufferSlice.getDescriptor();
|
descriptorInfo = res.bufferSlice.getDescriptor();
|
||||||
|
|
||||||
if (m_rcTracked.set(binding.resourceBinding)) {
|
m_cmd->track(res.bufferSlice.buffer(), (binding.access & vk::AccessWriteMask)
|
||||||
m_cmd->track(res.bufferSlice.buffer(), (binding.access & vk::AccessWriteMask)
|
? DxvkAccess::Write : DxvkAccess::Read);
|
||||||
? DxvkAccess::Write : DxvkAccess::Read);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
descriptorInfo.buffer.buffer = VK_NULL_HANDLE;
|
descriptorInfo.buffer.buffer = VK_NULL_HANDLE;
|
||||||
descriptorInfo.buffer.offset = 0;
|
descriptorInfo.buffer.offset = 0;
|
||||||
@ -5552,9 +5540,7 @@ namespace dxvk {
|
|||||||
m_state.vi.indexType);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5591,8 +5577,7 @@ namespace dxvk {
|
|||||||
newDynamicStrides &= strides[i] >= m_state.vi.vertexExtents[i];
|
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 {
|
} else {
|
||||||
buffers[i] = VK_NULL_HANDLE;
|
buffers[i] = VK_NULL_HANDLE;
|
||||||
offsets[i] = 0;
|
offsets[i] = 0;
|
||||||
@ -6669,10 +6654,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxvkContext::beginCurrentCommands() {
|
void DxvkContext::beginCurrentCommands() {
|
||||||
// Mark all resources as untracked
|
|
||||||
m_vbTracked.clear();
|
|
||||||
m_rcTracked.clear();
|
|
||||||
|
|
||||||
// The current state of the internal command buffer is
|
// The current state of the internal command buffer is
|
||||||
// undefined, so we have to bind and set up everything
|
// undefined, so we have to bind and set up everything
|
||||||
// before any draw or dispatch command is recorded.
|
// before any draw or dispatch command is recorded.
|
||||||
|
@ -177,9 +177,6 @@ namespace dxvk {
|
|||||||
void bindIndexBuffer(
|
void bindIndexBuffer(
|
||||||
DxvkBufferSlice&& buffer,
|
DxvkBufferSlice&& buffer,
|
||||||
VkIndexType indexType) {
|
VkIndexType indexType) {
|
||||||
if (!m_state.vi.indexBuffer.matchesBuffer(buffer))
|
|
||||||
m_vbTracked.clr(MaxNumVertexBindings);
|
|
||||||
|
|
||||||
m_state.vi.indexBuffer = std::move(buffer);
|
m_state.vi.indexBuffer = std::move(buffer);
|
||||||
m_state.vi.indexType = indexType;
|
m_state.vi.indexType = indexType;
|
||||||
|
|
||||||
@ -218,11 +215,6 @@ namespace dxvk {
|
|||||||
VkShaderStageFlags stages,
|
VkShaderStageFlags stages,
|
||||||
uint32_t slot,
|
uint32_t slot,
|
||||||
DxvkBufferSlice&& buffer) {
|
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_rc[slot].bufferSlice = std::move(buffer);
|
||||||
|
|
||||||
m_descriptorState.dirtyBuffers(stages);
|
m_descriptorState.dirtyBuffers(stages);
|
||||||
@ -261,7 +253,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_rc[slot].imageView = std::move(view);
|
m_rc[slot].imageView = std::move(view);
|
||||||
m_rcTracked.clr(slot);
|
|
||||||
|
|
||||||
m_descriptorState.dirtyViews(stages);
|
m_descriptorState.dirtyViews(stages);
|
||||||
}
|
}
|
||||||
@ -288,8 +279,6 @@ namespace dxvk {
|
|||||||
m_rc[slot].bufferView = nullptr;
|
m_rc[slot].bufferView = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rcTracked.clr(slot);
|
|
||||||
|
|
||||||
m_descriptorState.dirtyViews(stages);
|
m_descriptorState.dirtyViews(stages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +296,6 @@ namespace dxvk {
|
|||||||
uint32_t slot,
|
uint32_t slot,
|
||||||
Rc<DxvkSampler>&& sampler) {
|
Rc<DxvkSampler>&& sampler) {
|
||||||
m_rc[slot].sampler = std::move(sampler);
|
m_rc[slot].sampler = std::move(sampler);
|
||||||
m_rcTracked.clr(slot);
|
|
||||||
|
|
||||||
m_descriptorState.dirtyViews(stages);
|
m_descriptorState.dirtyViews(stages);
|
||||||
}
|
}
|
||||||
@ -371,9 +359,6 @@ namespace dxvk {
|
|||||||
uint32_t binding,
|
uint32_t binding,
|
||||||
DxvkBufferSlice&& buffer,
|
DxvkBufferSlice&& buffer,
|
||||||
uint32_t stride) {
|
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.vertexBuffers[binding] = std::move(buffer);
|
||||||
m_state.vi.vertexStrides[binding] = stride;
|
m_state.vi.vertexStrides[binding] = stride;
|
||||||
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
|
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
|
||||||
@ -1413,9 +1398,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxvkRenderTargetLayouts m_rtLayouts = { };
|
DxvkRenderTargetLayouts m_rtLayouts = { };
|
||||||
|
|
||||||
DxvkBindingSet<MaxNumVertexBindings + 1> m_vbTracked;
|
|
||||||
DxvkBindingSet<MaxNumResourceSlots> m_rcTracked;
|
|
||||||
|
|
||||||
std::vector<DxvkDeferredClear> m_deferredClears;
|
std::vector<DxvkDeferredClear> m_deferredClears;
|
||||||
|
|
||||||
std::vector<VkWriteDescriptorSet> m_descriptorWrites;
|
std::vector<VkWriteDescriptorSet> m_descriptorWrites;
|
||||||
|
@ -542,10 +542,18 @@ namespace dxvk {
|
|||||||
* command list and optimize certain transfer operations.
|
* command list and optimize certain transfer operations.
|
||||||
* \param [in] trackingId Tracking ID
|
* \param [in] trackingId Tracking ID
|
||||||
* \param [in] access Tracked access
|
* \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
|
// 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:
|
public:
|
||||||
|
|
||||||
template<typename T>
|
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)) {
|
: m_ptr(reinterpret_cast<uintptr_t>(static_cast<DxvkPagedResource*>(object.ptr())) | uintptr_t(access)) {
|
||||||
object->trackId(trackingId, access);
|
|
||||||
object.unsafeExtract()->convertRef(DxvkAccess::None, 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)) {
|
: m_ptr(reinterpret_cast<uintptr_t>(object) | uintptr_t(access)) {
|
||||||
object->trackId(trackingId, access);
|
|
||||||
object->acquire(access);
|
object->acquire(access);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user