layers: Accept non-unique shader caps
Change-Id: If14c4c58a6b6df04e97f0f83d8f8eb9b26e866ad
diff --git a/layers/shader_validation.cpp b/layers/shader_validation.cpp
index 0af30fb..4188556 100644
--- a/layers/shader_validation.cpp
+++ b/layers/shader_validation.cpp
@@ -1162,7 +1162,7 @@
using E = DeviceExtensions;
// clang-format off
- static const std::unordered_map<uint32_t, CapabilityInfo> capabilities = {
+ static const std::unordered_multimap<uint32_t, CapabilityInfo> capabilities = {
// Capabilities always supported by a Vulkan 1.0 implementation -- no
// feature bits.
{spv::CapabilityMatrix, {nullptr}},
@@ -1206,6 +1206,7 @@
{spv::CapabilityDrawParameters, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, nullptr, &E::vk_khr_shader_draw_parameters}},
{spv::CapabilityGeometryShaderPassthroughNV, {VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, nullptr, &E::vk_nv_geometry_shader_passthrough}},
{spv::CapabilitySampleMaskOverrideCoverageNV, {VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME, nullptr, &E::vk_nv_sample_mask_override_coverage}},
+ {spv::CapabilityShaderViewportIndexLayerEXT, {VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, nullptr, &E::vk_ext_shader_viewport_index_layer}},
{spv::CapabilityShaderViewportIndexLayerNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &E::vk_nv_viewport_array2}},
{spv::CapabilityShaderViewportMaskNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &E::vk_nv_viewport_array2}},
{spv::CapabilitySubgroupBallotKHR, {VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, nullptr, &E::vk_ext_shader_subgroup_ballot }},
@@ -1215,13 +1216,44 @@
for (auto insn : *src) {
if (insn.opcode() == spv::OpCapability) {
- auto it = capabilities.find(insn.word(1));
- if (it != capabilities.end()) {
- if (it->second.feature) {
- skip |= require_feature(report_data, enabledFeatures->*(it->second.feature), it->second.name);
+ size_t n = capabilities.count(insn.word(1));
+ if (1 == n) { // key occurs exactly once
+ auto it = capabilities.find(insn.word(1));
+ if (it != capabilities.end()) {
+ if (it->second.feature) {
+ skip |= require_feature(report_data, enabledFeatures->*(it->second.feature), it->second.name);
+ }
+ if (it->second.extension) {
+ skip |= require_extension(report_data, extensions->*(it->second.extension), it->second.name);
+ }
}
- if (it->second.extension) {
- skip |= require_extension(report_data, extensions->*(it->second.extension), it->second.name);
+ } else if (1 < n) { // key occurs multiple times, at least one must be enabled
+ bool needs_feature = false, has_feature = false;
+ bool needs_ext = false, has_ext = false;
+ std::string feature_names = "(one of) [ ";
+ std::string extension_names = feature_names;
+ auto caps = capabilities.equal_range(insn.word(1));
+ for (auto it = caps.first; it != caps.second; ++it) {
+ if (it->second.feature) {
+ needs_feature = true;
+ has_feature = has_feature || enabledFeatures->*(it->second.feature);
+ feature_names += it->second.name;
+ feature_names += " ";
+ }
+ if (it->second.extension) {
+ needs_ext = true;
+ has_ext = has_ext || extensions->*(it->second.extension);
+ extension_names += it->second.name;
+ extension_names += " ";
+ }
+ }
+ if (needs_feature) {
+ feature_names += "]";
+ skip |= require_feature(report_data, has_feature, feature_names.c_str());
+ }
+ if (needs_ext) {
+ extension_names += "]";
+ skip |= require_extension(report_data, has_ext, extension_names.c_str());
}
}
}