Validate VUID-RuntimeSpirv-Location-06428
This VUID is not validated anywhere in the layer's source code:
VUID-RuntimeSpirv-Location-06428 The maximum number of storage buffers, storage images, and output
Locationdecorated color attachments written to in theFragment Execution Modelmust be less than or equal to maxFragmentCombinedOutputResources
yes, this is similar to the maxFragmentDualSrcAttachments one (VUID-vkCmdDraw-maxFragmentDualSrcAttachments-09239) that we have coverage for
I remember I was going to do this one, but needed spec clarification (which was added https://gitlab.khronos.org/vulkan/vulkan/-/issues/2236) and just never got around back to adding this
wow, so finally got to this and tried to implement it as
// maxFragmentCombinedOutputResources
if (stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
// Variables can be aliased, so use Location to mark things as unique
vvl::unordered_set<uint32_t> color_attachments;
vvl::unordered_set<uint32_t> storage_buffers;
vvl::unordered_set<uint32_t> storage_images;
for (const auto *variable : entrypoint.user_defined_interface_variables) {
if (variable->storage_class == spv::StorageClassOutput && variable->decorations.location != spirv::kInvalidValue) {
// even if using an array of attachments in the shader, each used variable of the array is represented by a single variable
color_attachments.insert(variable->decorations.location);
}
}
for (const auto& variable : entrypoint.resource_interface_variables) {
if (variable.decorations.location == spirv::kInvalidValue) continue;
if (variable.is_storage_buffer) {
storage_buffers.insert(variable.decorations.location);
} else if (variable.is_storage_image) {
storage_images.insert(variable.decorations.location);
}
}
const uint32_t total_output = (uint32_t)(color_attachments.size() + storage_buffers.size() + storage_images.size());
if (total_output > limits.maxFragmentCombinedOutputResources) {
skip |= LogError("VUID-RuntimeSpirv-Location-06428", module_state.handle(), loc,
"SPIR-V (Fragment stage) output contains %zu storage buffer locations, %zu storage image locations, and %zu color attachments which together is %" PRIu32 " which exceeds the limit maxFragmentCombinedOutputResources (%" PRIu32 ").", storage_buffers.size(), storage_images.size(), color_attachments.size(), total_output, limits.maxFragmentCombinedOutputResources);
}
}
but then writing tests, I realized I have no idea what the "storage buffer" means (like do we count each set or each binding to the limit?)
created https://gitlab.khronos.org/vulkan/vulkan/-/issues/3900 to try this spec fixing again :crying_cat_face:
update - found out this was before descriptor indexing (and those drivers should report something like uint32_t max here). Also each descriptor (so binding) would count as 1