Store location values sparsely (#3488)
Fixes http://crbug.com/1102149
* Switch from boolean vectors to unordered sets for location storage
diff --git a/source/val/validate_interfaces.cpp b/source/val/validate_interfaces.cpp
index ed8cb9c..833734f 100644
--- a/source/val/validate_interfaces.cpp
+++ b/source/val/validate_interfaces.cpp
@@ -208,8 +208,8 @@
// 4 * location + component.
spv_result_t GetLocationsForVariable(
ValidationState_t& _, const Instruction* entry_point,
- const Instruction* variable, std::vector<bool>* locations,
- std::vector<bool>* output_index1_locations) {
+ const Instruction* variable, std::unordered_set<uint32_t>* locations,
+ std::unordered_set<uint32_t>* output_index1_locations) {
const bool is_fragment = entry_point->GetOperandAs<SpvExecutionModel>(0) ==
SpvExecutionModelFragment;
const bool is_output =
@@ -356,17 +356,13 @@
auto locs = locations;
if (has_index && index == 1) locs = output_index1_locations;
- if (end > locs->size()) {
- locs->resize(end, false);
- }
for (uint32_t i = start; i < end; ++i) {
- if (locs->at(i)) {
+ if (!locs->insert(i).second) {
return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
<< "Entry-point has conflicting " << storage_class
<< " location assignment at location " << i / 4
<< ", component " << i % 4;
}
- (*locs)[i] = true;
}
}
} else {
@@ -425,17 +421,13 @@
start += component;
end = location * 4 + component + num_components;
}
- if (end > locations->size()) {
- locations->resize(end, false);
- }
for (uint32_t l = start; l < end; ++l) {
- if (locations->at(l)) {
+ if (!locations->insert(l).second) {
return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
<< "Entry-point has conflicting " << storage_class
<< " location assignment at location " << l / 4
<< ", component " << l % 4;
}
- (*locations)[l] = true;
}
}
}
@@ -445,10 +437,10 @@
spv_result_t ValidateLocations(ValidationState_t& _,
const Instruction* entry_point) {
- // Reserve space for 16 locations with 4 components each.
- std::vector<bool> input_locations(16 * 4, false);
- std::vector<bool> output_locations_index0(16 * 4, false);
- std::vector<bool> output_locations_index1(16 * 4, false);
+ // Locations are stored as a combined location and component values.
+ std::unordered_set<uint32_t> input_locations;
+ std::unordered_set<uint32_t> output_locations_index0;
+ std::unordered_set<uint32_t> output_locations_index1;
for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
auto interface_var = _.FindDef(interface_id);
diff --git a/test/val/val_interfaces_test.cpp b/test/val/val_interfaces_test.cpp
index c274fec..f2fb45a 100644
--- a/test/val/val_interfaces_test.cpp
+++ b/test/val/val_interfaces_test.cpp
@@ -1356,6 +1356,29 @@
"assignment at location 1, component 1"));
}
+TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
+ const std::string text = R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "????????" %17
+ OpExecutionMode %4 OriginUpperLeft
+ OpDecorate %17 Location 4227868160
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v3float = OpTypeVector %float 3
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+ %17 = OpVariable %_ptr_Input_v3float Input
+ %4 = OpFunction %void None %3
+ %5 = OpLabel
+ OpUnreachable
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
} // namespace
} // namespace val
} // namespace spvtools