mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-13 16:08:50 +01:00
[dxvk] Optimize descriptor set binding further
This commit is contained in:
parent
f9e6d8e23a
commit
15cf130369
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user