Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BestPractices: Add warning if allocated descriptors exceeds pool max #9224

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions layers/best_practices/bp_descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ bool BestPractices::PreCallValidateAllocateDescriptorSets(VkDevice device, const
". This pool only has %" PRIu32 " descriptorSets remaining.",
pAllocateInfo->descriptorSetCount, FormatHandle(*pool_state).c_str(), pool_state->GetAvailableSets());
}
auto ads_pool_state = Get<vvl::DescriptorPool>(pAllocateInfo->descriptorPool);
for (auto it = ads_state_data.required_descriptors_by_type.begin(); it != ads_state_data.required_descriptors_by_type.end();
++it) {
auto available_count = ads_pool_state->GetAvailableCount(it->first);

if (ads_state_data.required_descriptors_by_type.at(it->first) > available_count) {
skip |= LogWarning(
"BestPractices-vkAllocateDescriptorSets-EmptyDescriptorPoolType", ads_pool_state->Handle(), error_obj.location,
"Unable to allocate %" PRIu32
" descriptors of type %s from %s"
". This pool only has %" PRIu32 " descriptors of this type remaining.",
ads_state_data.required_descriptors_by_type.at(it->first), string_VkDescriptorType(VkDescriptorType(it->first)),
FormatHandle(*ads_pool_state).c_str(), available_count);
}
}
}

return skip;
Expand All @@ -74,8 +89,7 @@ void BestPractices::ManualPostCallRecordAllocateDescriptorSets(VkDevice device,

void BestPractices::PostCallRecordFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets, const RecordObject& record_obj) {
BaseClass::PostCallRecordFreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets,
record_obj);
BaseClass::PostCallRecordFreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets, record_obj);
if (record_obj.result == VK_SUCCESS) {
// we want to track frees because we're interested in suggesting re-use
if (auto pool_state = Get<bp_state::DescriptorPool>(descriptorPool)) {
Expand Down
41 changes: 41 additions & 0 deletions tests/unit/best_practices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,47 @@ TEST_F(VkBestPracticesLayerTest, OverAllocateFromDescriptorPool) {
m_errorMonitor->VerifyFound();
}

TEST_F(VkBestPracticesLayerTest, OverAllocateTypeFromDescriptorPool) {
TEST_DESCRIPTION("Attempt to allocate more sets and descriptors than descriptor pool has available.");

SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(InitBestPracticesFramework());
RETURN_IF_SKIP(InitState());
InitRenderTarget();

VkDescriptorPoolSize ds_type_count = {};
ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER;
ds_type_count.descriptorCount = 1;

VkDescriptorPoolCreateInfo ds_pool_ci = vku::InitStructHelper();
ds_pool_ci.flags = 0;
ds_pool_ci.maxSets = 2;
ds_pool_ci.poolSizeCount = 1;
ds_pool_ci.pPoolSizes = &ds_type_count;

vkt::DescriptorPool ds_pool(*m_device, ds_pool_ci);

VkDescriptorSetLayoutBinding dsl_binding_samp = {};
dsl_binding_samp.binding = 0;
dsl_binding_samp.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
dsl_binding_samp.descriptorCount = 1;
dsl_binding_samp.stageFlags = VK_SHADER_STAGE_ALL;
dsl_binding_samp.pImmutableSamplers = NULL;

const vkt::DescriptorSetLayout ds_layout_samp(*m_device, {dsl_binding_samp});

// Try to allocate 2 sets when pool only has 1 set
VkDescriptorSet descriptor_sets[2];
VkDescriptorSetLayout set_layouts[2] = {ds_layout_samp.handle(), ds_layout_samp.handle()};
VkDescriptorSetAllocateInfo alloc_info = vku::InitStructHelper();
alloc_info.descriptorSetCount = 2;
alloc_info.descriptorPool = ds_pool.handle();
alloc_info.pSetLayouts = set_layouts;
m_errorMonitor->SetDesiredWarning("BestPractices-vkAllocateDescriptorSets-EmptyDescriptorPoolType");
HildarTheDorf marked this conversation as resolved.
Show resolved Hide resolved
vk::AllocateDescriptorSets(device(), &alloc_info, descriptor_sets);
m_errorMonitor->VerifyFound();
}

TEST_F(VkBestPracticesLayerTest, RenderPassClearWithoutLoadOpClear) {
TEST_DESCRIPTION("Test for clearing a RenderPass with non-zero clearValueCount without any VK_ATTACHMENT_LOAD_OP_CLEAR");

Expand Down
Loading