1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-13 07:08:50 +01:00

[dxvk] Optimize descriptor set binding further

This commit is contained in:
Philip Rebohle 2022-06-16 15:13:14 +02:00
parent f9e6d8e23a
commit 15cf130369
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -4161,184 +4161,190 @@ namespace dxvk {
DxvkBindingMask newBindMask = refBindMask; DxvkBindingMask newBindMask = refBindMask;
uint32_t layoutSetMask = layout->getSetMask();
uint32_t dirtySetMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS uint32_t dirtySetMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
? m_descriptorState.getDirtyGraphicsSets() ? m_descriptorState.getDirtyGraphicsSets()
: m_descriptorState.getDirtyComputeSets(); : m_descriptorState.getDirtyComputeSets();
dirtySetMask &= layoutSetMask;
uint32_t bindingIndex = 0; uint32_t firstUpdated = bit::tzcnt(dirtySetMask);
uint32_t firstUpdated = DxvkDescriptorSets::SetCount;
while (dirtySetMask) {
uint32_t setIndex = bit::tzcnt(dirtySetMask);
for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) {
// Initialize binding mask for the current set, only // Initialize binding mask for the current set, only
// clear bits if certain resources are actually unbound. // clear bits if certain resources are actually unbound.
uint32_t bindingCount = bindings.getBindingCount(i); uint32_t bindingIndex = layout->getFirstBinding(setIndex);
uint32_t bindingCount = bindings.getBindingCount(setIndex);
if ((dirtySetMask & (1u << i)) || !m_descriptorState.getSet<BindPoint>(i)) { newBindMask.setRange(bindingIndex, bindingCount);
firstUpdated = std::min(firstUpdated, i);
newBindMask.setRange(bindingIndex, bindingCount);
for (uint32_t j = 0; j < bindingCount; j++) { for (uint32_t j = 0; j < bindingCount; j++) {
const auto& binding = bindings.getBinding(i, j); const auto& binding = bindings.getBinding(setIndex, j);
switch (binding.descriptorType) { switch (binding.descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER: { case VK_DESCRIPTOR_TYPE_SAMPLER: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.sampler != nullptr) { if (res.sampler != nullptr) {
descriptors[j].image.sampler = res.sampler->handle(); descriptors[j].image.sampler = res.sampler->handle();
descriptors[j].image.imageView = VK_NULL_HANDLE; descriptors[j].image.imageView = VK_NULL_HANDLE;
descriptors[j].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; descriptors[j].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
if (m_rcTracked.set(binding.resourceBinding)) if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::None>(res.sampler); m_cmd->trackResource<DxvkAccess::None>(res.sampler);
} else { } else {
descriptors[j].image = m_common->dummyResources().samplerDescriptor(); descriptors[j].image = m_common->dummyResources().samplerDescriptor();
}
} break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
const auto& res = m_rc[binding.resourceBinding];
if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
descriptors[j].image.sampler = VK_NULL_HANDLE;
descriptors[j].image.imageView = res.imageView->handle(binding.viewType);
descriptors[j].image.imageLayout = res.imageView->imageInfo().layout;
if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.imageView);
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
} }
} break; } else {
descriptors[j].image = m_common->dummyResources().imageViewDescriptor(binding.viewType, true);
newBindMask.clr(bindingIndex + j);
}
} break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: { case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) { if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
descriptors[j].image.sampler = VK_NULL_HANDLE; descriptors[j].image.sampler = VK_NULL_HANDLE;
descriptors[j].image.imageView = res.imageView->handle(binding.viewType); descriptors[j].image.imageView = res.imageView->handle(binding.viewType);
descriptors[j].image.imageLayout = res.imageView->imageInfo().layout; descriptors[j].image.imageLayout = res.imageView->imageInfo().layout;
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.imageView); m_cmd->trackResource<DxvkAccess::None>(res.imageView);
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image()); m_cmd->trackResource<DxvkAccess::Write>(res.imageView->image());
}
} else {
descriptors[j].image = m_common->dummyResources().imageViewDescriptor(binding.viewType, true);
newBindMask.clr(bindingIndex + j);
} }
} break; } else {
descriptors[j].image = m_common->dummyResources().imageViewDescriptor(binding.viewType, false);
newBindMask.clr(bindingIndex + j);
}
} break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.imageView != nullptr && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) { if (res.sampler != nullptr && res.imageView != nullptr
descriptors[j].image.sampler = VK_NULL_HANDLE; && res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) {
descriptors[j].image.imageView = res.imageView->handle(binding.viewType); descriptors[j].image.sampler = res.sampler->handle();
descriptors[j].image.imageLayout = res.imageView->imageInfo().layout; descriptors[j].image.imageView = res.imageView->handle(binding.viewType);
descriptors[j].image.imageLayout = res.imageView->imageInfo().layout;
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.imageView); m_cmd->trackResource<DxvkAccess::None>(res.sampler);
m_cmd->trackResource<DxvkAccess::Write>(res.imageView->image()); m_cmd->trackResource<DxvkAccess::None>(res.imageView);
} m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
} else {
descriptors[j].image = m_common->dummyResources().imageViewDescriptor(binding.viewType, false);
newBindMask.clr(bindingIndex + j);
} }
} break; } else {
descriptors[j].image = m_common->dummyResources().imageSamplerDescriptor(binding.viewType);
newBindMask.clr(bindingIndex + j);
}
} break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.sampler != nullptr && res.imageView != nullptr if (res.bufferView != nullptr) {
&& res.imageView->handle(binding.viewType) != VK_NULL_HANDLE) { res.bufferView->updateView();
descriptors[j].image.sampler = res.sampler->handle(); descriptors[j].texelBuffer = res.bufferView->handle();
descriptors[j].image.imageView = res.imageView->handle(binding.viewType);
descriptors[j].image.imageLayout = res.imageView->imageInfo().layout;
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.sampler); m_cmd->trackResource<DxvkAccess::None>(res.bufferView);
m_cmd->trackResource<DxvkAccess::None>(res.imageView); m_cmd->trackResource<DxvkAccess::Read>(res.bufferView->buffer());
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
}
} else {
descriptors[j].image = m_common->dummyResources().imageSamplerDescriptor(binding.viewType);
newBindMask.clr(bindingIndex + j);
} }
} break; } else {
descriptors[j].texelBuffer = m_common->dummyResources().bufferViewDescriptor();
newBindMask.clr(bindingIndex + j);
}
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: { case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.bufferView != nullptr) { if (res.bufferView != nullptr) {
res.bufferView->updateView(); res.bufferView->updateView();
descriptors[j].texelBuffer = res.bufferView->handle(); descriptors[j].texelBuffer = res.bufferView->handle();
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.bufferView); m_cmd->trackResource<DxvkAccess::None>(res.bufferView);
m_cmd->trackResource<DxvkAccess::Read>(res.bufferView->buffer()); m_cmd->trackResource<DxvkAccess::Write>(res.bufferView->buffer());
}
} else {
descriptors[j].texelBuffer = m_common->dummyResources().bufferViewDescriptor();
newBindMask.clr(bindingIndex + j);
} }
} break; } else {
descriptors[j].texelBuffer = m_common->dummyResources().bufferViewDescriptor();
newBindMask.clr(bindingIndex + j);
}
} break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.bufferView != nullptr) { if (res.bufferSlice.defined()) {
res.bufferView->updateView(); descriptors[j] = res.bufferSlice.getDescriptor();
descriptors[j].texelBuffer = res.bufferView->handle();
if (m_rcTracked.set(binding.resourceBinding)) { if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::None>(res.bufferView); m_cmd->trackResource<DxvkAccess::Read>(res.bufferSlice.buffer());
m_cmd->trackResource<DxvkAccess::Write>(res.bufferView->buffer()); } else {
} descriptors[j].buffer = m_common->dummyResources().bufferDescriptor();
} else { }
descriptors[j].texelBuffer = m_common->dummyResources().bufferViewDescriptor(); } break;
newBindMask.clr(bindingIndex + j);
}
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: { case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
const auto& res = m_rc[binding.resourceBinding]; const auto& res = m_rc[binding.resourceBinding];
if (res.bufferSlice.defined()) { if (res.bufferSlice.defined()) {
descriptors[j] = res.bufferSlice.getDescriptor(); descriptors[j] = res.bufferSlice.getDescriptor();
if (m_rcTracked.set(binding.resourceBinding)) if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::Read>(res.bufferSlice.buffer()); m_cmd->trackResource<DxvkAccess::Write>(res.bufferSlice.buffer());
} else { } else {
descriptors[j].buffer = m_common->dummyResources().bufferDescriptor(); descriptors[j].buffer = m_common->dummyResources().bufferDescriptor();
} newBindMask.clr(bindingIndex + j);
} break; }
} break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: { default:
const auto& res = m_rc[binding.resourceBinding]; Logger::err(str::format("DxvkContext: Unhandled descriptor type: ", binding.descriptorType));
if (res.bufferSlice.defined()) {
descriptors[j] = res.bufferSlice.getDescriptor();
if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::Write>(res.bufferSlice.buffer());
} else {
descriptors[j].buffer = m_common->dummyResources().bufferDescriptor();
newBindMask.clr(bindingIndex + j);
}
} break;
default:
Logger::err(str::format("DxvkContext: Unhandled descriptor type: ", binding.descriptorType));
}
}
// Create and populate descriptor set with the given descriptors
VkDescriptorSet& set = m_descriptorState.getSet<BindPoint>(i);
set = allocateDescriptorSet(layout->getSetLayout(i));
if (bindingCount) {
m_cmd->updateDescriptorSetWithTemplate(set,
layout->getSetUpdateTemplate(i), descriptors.data());
} }
} }
bindingIndex += bindingCount; // Create and populate descriptor set with the given descriptors
VkDescriptorSet& set = m_descriptorState.getSet<BindPoint>(setIndex);
set = allocateDescriptorSet(layout->getSetLayout(setIndex));
m_cmd->updateDescriptorSetWithTemplate(set,
layout->getSetUpdateTemplate(setIndex), descriptors.data());
dirtySetMask &= dirtySetMask - 1;
} }
// Bind all updated descriptor sets // Bind all descriptor sets that need updating
uint32_t setCount = DxvkDescriptorSets::SetCount - firstUpdated; uint32_t bindSetMask = layoutSetMask & ~((1u << firstUpdated) - 1);
const VkDescriptorSet* setData = &m_descriptorState.getSet<BindPoint>(firstUpdated);
m_cmd->cmdBindDescriptorSets(BindPoint, while (bindSetMask) {
layout->getPipelineLayout(), uint32_t setIndex = bit::tzcnt(bindSetMask);
firstUpdated, setCount, setData,
0, nullptr); VkDescriptorSet& set = m_descriptorState.getSet<BindPoint>(setIndex);
m_cmd->cmdBindDescriptorSets(BindPoint,
layout->getPipelineLayout(),
setIndex, 1, &set, 0, nullptr);
bindSetMask &= bindSetMask - 1;
}
// Update pipeline if there are unbound resources // Update pipeline if there are unbound resources
if (refBindMask != newBindMask) { if (refBindMask != newBindMask) {