chassis: Drastically reduce chassis.cpp compile times
ValidationObject::InitObjectDispatchVectors() was previously, after
macro expansion, a ~40000 line function. Some compilers don't handle
huge functions well when performing optimzations, especially ones with
lots of control flow.
Rather than copy pasting a loop ~1000 times, make the loop into a lambda
and call it ~1000 times.
This reduces the compile time of chassis.cpp on my machine from 154s to 33s.
Fixes #2889.
diff --git a/layers/generated/chassis_dispatch_helper.h b/layers/generated/chassis_dispatch_helper.h
index babc046..12caa71 100644
--- a/layers/generated/chassis_dispatch_helper.h
+++ b/layers/generated/chassis_dispatch_helper.h
@@ -1150,46 +1150,67 @@
InterceptIdCount,
} InterceptId;
-
-#define INTERCEPTIDNAME(name) InterceptId ## name
-#define BUILD_DISPATCH_VECTOR(name) \
- for (auto item : object_dispatch) { \
- auto intercept_vector = &intercept_vectors[INTERCEPTIDNAME(name)]; \
- switch (item->container_type) { \
- case LayerObjectTypeThreading: \
- if (typeid(&ThreadSafety::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeParameterValidation: \
- if (typeid(&StatelessValidation::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeObjectTracker: \
- if (typeid(&ObjectLifetimes::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeCoreValidation: \
- if (typeid(&CoreChecks::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeBestPractices: \
- if (typeid(&BestPractices::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeGpuAssisted: \
- if (typeid(&GpuAssisted::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeDebugPrintf: \
- if (typeid(&DebugPrintf::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeSyncValidation: \
- if (typeid(&SyncValidator::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \
- break; \
- case LayerObjectTypeInstance: \
- case LayerObjectTypeDevice: \
- break; \
- default: \
- /* Chassis codegen needs to be updated for unknown validation object type */ \
- assert(0); \
- } \
- }
-
void ValidationObject::InitObjectDispatchVectors() {
+
+#define BUILD_DISPATCH_VECTOR(name) \
+ init_object_dispatch_vector(InterceptId ## name, \
+ typeid(&ValidationObject::name), \
+ typeid(&ThreadSafety::name), \
+ typeid(&StatelessValidation::name), \
+ typeid(&ObjectLifetimes::name), \
+ typeid(&CoreChecks::name), \
+ typeid(&BestPractices::name), \
+ typeid(&GpuAssisted::name), \
+ typeid(&DebugPrintf::name), \
+ typeid(&SyncValidator::name));
+
+ auto init_object_dispatch_vector = [this](InterceptId id,
+ const std::type_info& vo_typeid,
+ const std::type_info& tt_typeid,
+ const std::type_info& tpv_typeid,
+ const std::type_info& tot_typeid,
+ const std::type_info& tcv_typeid,
+ const std::type_info& tbp_typeid,
+ const std::type_info& tga_typeid,
+ const std::type_info& tdp_typeid,
+ const std::type_info& tsv_typeid) {
+ for (auto item : this->object_dispatch) {
+ auto intercept_vector = &this->intercept_vectors[id];
+ switch (item->container_type) {
+ case LayerObjectTypeThreading:
+ if (tt_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeParameterValidation:
+ if (tpv_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeObjectTracker:
+ if (tot_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeCoreValidation:
+ if (tcv_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeBestPractices:
+ if (tbp_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeGpuAssisted:
+ if (tga_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeDebugPrintf:
+ if (tdp_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeSyncValidation:
+ if (tsv_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeInstance:
+ case LayerObjectTypeDevice:
+ break;
+ default:
+ /* Chassis codegen needs to be updated for unknown validation object type */
+ assert(0);
+ }
+ }
+ };
+
intercept_vectors.resize(InterceptIdCount);
BUILD_DISPATCH_VECTOR(PreCallValidateGetDeviceQueue);
diff --git a/scripts/layer_chassis_generator.py b/scripts/layer_chassis_generator.py
index c87d2df..f945d97 100644
--- a/scripts/layer_chassis_generator.py
+++ b/scripts/layer_chassis_generator.py
@@ -1709,46 +1709,65 @@
return VK_SUCCESS;
}"""
- inline_dispatch_vector_macro_defs = """
-
-#define INTERCEPTIDNAME(name) InterceptId ## name
+ init_object_dispatch_vector = """
#define BUILD_DISPATCH_VECTOR(name) \\
- for (auto item : object_dispatch) { \\
- auto intercept_vector = &intercept_vectors[INTERCEPTIDNAME(name)]; \\
- switch (item->container_type) { \\
- case LayerObjectTypeThreading: \\
- if (typeid(&ThreadSafety::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeParameterValidation: \\
- if (typeid(&StatelessValidation::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeObjectTracker: \\
- if (typeid(&ObjectLifetimes::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeCoreValidation: \\
- if (typeid(&CoreChecks::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeBestPractices: \\
- if (typeid(&BestPractices::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeGpuAssisted: \\
- if (typeid(&GpuAssisted::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeDebugPrintf: \\
- if (typeid(&DebugPrintf::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeSyncValidation: \\
- if (typeid(&SyncValidator::name) != typeid(&ValidationObject::name)) intercept_vector->push_back(item); \\
- break; \\
- case LayerObjectTypeInstance: \\
- case LayerObjectTypeDevice: \\
- break; \\
- default: \\
- /* Chassis codegen needs to be updated for unknown validation object type */ \\
- assert(0); \\
- } \\
- }"""
+ init_object_dispatch_vector(InterceptId ## name, \\
+ typeid(&ValidationObject::name), \\
+ typeid(&ThreadSafety::name), \\
+ typeid(&StatelessValidation::name), \\
+ typeid(&ObjectLifetimes::name), \\
+ typeid(&CoreChecks::name), \\
+ typeid(&BestPractices::name), \\
+ typeid(&GpuAssisted::name), \\
+ typeid(&DebugPrintf::name), \\
+ typeid(&SyncValidator::name));
+ auto init_object_dispatch_vector = [this](InterceptId id,
+ const std::type_info& vo_typeid,
+ const std::type_info& tt_typeid,
+ const std::type_info& tpv_typeid,
+ const std::type_info& tot_typeid,
+ const std::type_info& tcv_typeid,
+ const std::type_info& tbp_typeid,
+ const std::type_info& tga_typeid,
+ const std::type_info& tdp_typeid,
+ const std::type_info& tsv_typeid) {
+ for (auto item : this->object_dispatch) {
+ auto intercept_vector = &this->intercept_vectors[id];
+ switch (item->container_type) {
+ case LayerObjectTypeThreading:
+ if (tt_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeParameterValidation:
+ if (tpv_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeObjectTracker:
+ if (tot_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeCoreValidation:
+ if (tcv_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeBestPractices:
+ if (tbp_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeGpuAssisted:
+ if (tga_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeDebugPrintf:
+ if (tdp_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeSyncValidation:
+ if (tsv_typeid != vo_typeid) intercept_vector->push_back(item);
+ break;
+ case LayerObjectTypeInstance:
+ case LayerObjectTypeDevice:
+ break;
+ default:
+ /* Chassis codegen needs to be updated for unknown validation object type */
+ assert(0);
+ }
+ }
+ };"""
def __init__(self,
errFile = sys.stderr,
@@ -1833,10 +1852,10 @@
helper_content += 'typedef enum InterceptId{\n'
helper_content += self.intercept_enums
helper_content += ' InterceptIdCount,\n'
- helper_content += '} InterceptId;\n'
- helper_content += self.inline_dispatch_vector_macro_defs
- helper_content += '\n\n'
+ helper_content += '} InterceptId;\n\n'
helper_content += 'void ValidationObject::InitObjectDispatchVectors() {\n'
+ helper_content += self.init_object_dispatch_vector
+ helper_content += '\n\n'
helper_content += ' intercept_vectors.resize(InterceptIdCount);\n\n'
helper_content += self.dispatch_vector_fcns;
helper_content += '};\n'