diff options
author | Pankaj Mistry <63069047+pmistryNV@users.noreply.github.com> | 2022-09-02 03:36:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-02 03:36:15 +0300 |
commit | 4c456f7da67c5437a6fb7d4d20d78e2a5ae2acf2 (patch) | |
tree | edc3b0df2b30f2baba2b2e3ca6fd0056dcd65489 /source | |
parent | 33113abf453572d3cf61b58d4378bbacb4206b1a (diff) |
Implement tool changes for SPV_EXT_mesh_shader. (#4915)tmp-1.3.230
- Added validation rule to support EXT_mesh_shader from SPIRV 1.4 onwards
Diffstat (limited to 'source')
-rw-r--r-- | source/opt/instrument_pass.cpp | 7 | ||||
-rw-r--r-- | source/val/validate_atomics.cpp | 8 | ||||
-rw-r--r-- | source/val/validate_barriers.cpp | 3 | ||||
-rw-r--r-- | source/val/validate_builtins.cpp | 71 | ||||
-rw-r--r-- | source/val/validate_extensions.cpp | 6 | ||||
-rw-r--r-- | source/val/validate_memory.cpp | 3 | ||||
-rw-r--r-- | source/val/validate_mode_setting.cpp | 30 | ||||
-rw-r--r-- | source/val/validate_scopes.cpp | 13 | ||||
-rw-r--r-- | source/val/validation_state.cpp | 5 |
9 files changed, 105 insertions, 41 deletions
diff --git a/source/opt/instrument_pass.cpp b/source/opt/instrument_pass.cpp index 3d48b321b..d143d5959 100644 --- a/source/opt/instrument_pass.cpp +++ b/source/opt/instrument_pass.cpp @@ -245,7 +245,9 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx, } break; case SpvExecutionModelGLCompute: case SpvExecutionModelTaskNV: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelTaskEXT: + case SpvExecutionModelMeshEXT: { // Load and store GlobalInvocationId. uint32_t load_id = GenVarLoad( context()->GetBuiltinInputVarId(SpvBuiltInGlobalInvocationId), @@ -1064,7 +1066,8 @@ bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) { stage != SpvExecutionModelAnyHitNV && stage != SpvExecutionModelClosestHitNV && stage != SpvExecutionModelMissNV && - stage != SpvExecutionModelCallableNV) { + stage != SpvExecutionModelCallableNV && + stage != SpvExecutionModelTaskEXT && stage != SpvExecutionModelMeshEXT) { if (consumer()) { std::string message = "Stage not supported by instrumentation"; consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str()); diff --git a/source/val/validate_atomics.cpp b/source/val/validate_atomics.cpp index 3b0a7fa8e..bf565c310 100644 --- a/source/val/validate_atomics.cpp +++ b/source/val/validate_atomics.cpp @@ -40,6 +40,7 @@ bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) { case SpvStorageClassImage: case SpvStorageClassFunction: case SpvStorageClassPhysicalStorageBuffer: + case SpvStorageClassTaskPayloadWorkgroupEXT: return true; break; default: @@ -206,12 +207,13 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) { (storage_class != SpvStorageClassStorageBuffer) && (storage_class != SpvStorageClassWorkgroup) && (storage_class != SpvStorageClassImage) && - (storage_class != SpvStorageClassPhysicalStorageBuffer)) { + (storage_class != SpvStorageClassPhysicalStorageBuffer) && + (storage_class != SpvStorageClassTaskPayloadWorkgroupEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << _.VkErrorID(4686) << spvOpcodeString(opcode) << ": Vulkan spec only allows storage classes for atomic to " - "be: Uniform, Workgroup, Image, StorageBuffer, or " - "PhysicalStorageBuffer."; + "be: Uniform, Workgroup, Image, StorageBuffer, " + "PhysicalStorageBuffer or TaskPayloadWorkgroupEXT."; } } else if (storage_class == SpvStorageClassFunction) { return _.diag(SPV_ERROR_INVALID_DATA, inst) diff --git a/source/val/validate_barriers.cpp b/source/val/validate_barriers.cpp index 3a9e3e7c5..03225d86a 100644 --- a/source/val/validate_barriers.cpp +++ b/source/val/validate_barriers.cpp @@ -50,7 +50,8 @@ spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) { *message = "OpControlBarrier requires one of the following " "Execution " - "Models: TessellationControl, GLCompute or Kernel"; + "Models: TessellationControl, GLCompute, Kernel, " + "MeshNV or TaskNV"; } return false; } diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp index 379705ac0..40a36d062 100644 --- a/source/val/validate_builtins.cpp +++ b/source/val/validate_builtins.cpp @@ -1179,9 +1179,16 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference( &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be " "used for variables with Input storage class if execution model is " - "Vertex.", + "MeshNV.", SpvExecutionModelMeshNV, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); + id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( + &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, + "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be " + "used for variables with Input storage class if execution model is " + "MeshEXT.", + SpvExecutionModelMeshEXT, decoration, built_in_inst, + referenced_from_inst, std::placeholders::_1)); } if (storage_class == SpvStorageClassOutput) { @@ -1224,7 +1231,8 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference( case SpvExecutionModelTessellationControl: case SpvExecutionModelTessellationEvaluation: case SpvExecutionModelGeometry: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: { if (decoration.struct_member_index() != Decoration::kInvalidMember) { // The outer level of array is applied on the variable. if (spv_result_t error = ValidateF32Arr( @@ -1856,7 +1864,8 @@ spv_result_t BuiltInsValidator::ValidatePointSizeAtReference( case SpvExecutionModelTessellationControl: case SpvExecutionModelTessellationEvaluation: case SpvExecutionModelGeometry: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: { // PointSize can be a per-vertex variable for tessellation control, // tessellation evaluation and geometry shader stages. In such cases // variables will have an array of 32-bit floats. @@ -1957,6 +1966,13 @@ spv_result_t BuiltInsValidator::ValidatePositionAtReference( "with Input storage class if execution model is MeshNV.", SpvExecutionModelMeshNV, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); + id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( + &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319, + "Vulkan spec doesn't allow BuiltIn Position to be used " + "for variables " + "with Input storage class if execution model is MeshEXT.", + SpvExecutionModelMeshEXT, decoration, built_in_inst, + referenced_from_inst, std::placeholders::_1)); } for (const SpvExecutionModel execution_model : execution_models_) { @@ -1980,7 +1996,8 @@ spv_result_t BuiltInsValidator::ValidatePositionAtReference( case SpvExecutionModelGeometry: case SpvExecutionModelTessellationControl: case SpvExecutionModelTessellationEvaluation: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: { // Position can be a per-vertex variable for tessellation control, // tessellation evaluation, geometry and mesh shader stages. In such // cases variables will have an array of 4-component 32-bit float @@ -2151,6 +2168,7 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtReference( case SpvExecutionModelTessellationEvaluation: case SpvExecutionModelGeometry: case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: case SpvExecutionModelIntersectionKHR: case SpvExecutionModelAnyHitKHR: case SpvExecutionModelClosestHitKHR: { @@ -2163,9 +2181,8 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtReference( << _.VkErrorID(4330) << "Vulkan spec allows BuiltIn PrimitiveId to be used only " "with Fragment, TessellationControl, " - "TessellationEvaluation, Geometry, MeshNV, " - "IntersectionKHR, " - "AnyHitKHR, and ClosestHitKHR execution models. " + "TessellationEvaluation, Geometry, MeshNV, MeshEXT, " + "IntersectionKHR, AnyHitKHR, and ClosestHitKHR execution models. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -2713,7 +2730,8 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( assert(function_id_ == 0); for (const auto em : {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation, - SpvExecutionModelGeometry, SpvExecutionModelMeshNV}) { + SpvExecutionModelGeometry, SpvExecutionModelMeshNV, + SpvExecutionModelMeshEXT}) { id_to_at_reference_checks_[referenced_from_inst.id()].push_back( std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, ((operand == SpvBuiltInLayer) ? 4274 : 4406), @@ -2721,7 +2739,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( "ViewportIndex to be " "used for variables with Input storage class if " "execution model is Vertex, TessellationEvaluation, " - "Geometry, or MeshNV.", + "Geometry, MeshNV or MeshEXT.", em, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); } @@ -2746,6 +2764,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( case SpvExecutionModelGeometry: case SpvExecutionModelFragment: case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: // Ok. break; case SpvExecutionModelVertex: @@ -2925,7 +2944,10 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference( for (const SpvExecutionModel execution_model : execution_models_) { bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute || execution_model == SpvExecutionModelTaskNV || - execution_model == SpvExecutionModelMeshNV; + execution_model == SpvExecutionModelMeshNV || + execution_model == SpvExecutionModelTaskEXT || + execution_model == SpvExecutionModelMeshEXT; + if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) { uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel); return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -2933,7 +2955,8 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference( << spvLogStringForEnv(_.context()->target_env) << " spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin) - << " to be used only with GLCompute, MeshNV, or TaskNV execution model. " + << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or" + << " TaskEXT execution model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -3007,7 +3030,9 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference( for (const SpvExecutionModel execution_model : execution_models_) { bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute || execution_model == SpvExecutionModelTaskNV || - execution_model == SpvExecutionModelMeshNV; + execution_model == SpvExecutionModelMeshNV || + execution_model == SpvExecutionModelTaskEXT || + execution_model == SpvExecutionModelMeshEXT; if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) { uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel); return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -3015,7 +3040,8 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference( << spvLogStringForEnv(_.context()->target_env) << " spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin) - << " to be used only with GLCompute, MeshNV, or TaskNV execution model. " + << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or " + << "TaskEXT execution model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -3159,14 +3185,17 @@ spv_result_t BuiltInsValidator::ValidateWorkgroupSizeAtReference( for (const SpvExecutionModel execution_model : execution_models_) { if (execution_model != SpvExecutionModelGLCompute && execution_model != SpvExecutionModelTaskNV && - execution_model != SpvExecutionModelMeshNV) { + execution_model != SpvExecutionModelMeshNV && + execution_model != SpvExecutionModelTaskEXT && + execution_model != SpvExecutionModelMeshEXT) { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) << _.VkErrorID(4425) << spvLogStringForEnv(_.context()->target_env) << " spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) - << " to be used only with GLCompute, MeshNV, or TaskNV execution model. " + << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or " + << "TaskEXT execution model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -3297,12 +3326,15 @@ spv_result_t BuiltInsValidator::ValidateDrawIndexAtReference( for (const SpvExecutionModel execution_model : execution_models_) { if (execution_model != SpvExecutionModelVertex && execution_model != SpvExecutionModelMeshNV && - execution_model != SpvExecutionModelTaskNV) { + execution_model != SpvExecutionModelTaskNV && + execution_model != SpvExecutionModelMeshEXT && + execution_model != SpvExecutionModelTaskEXT) { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) << _.VkErrorID(4207) << "Vulkan spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, operand) - << " to be used only with Vertex, MeshNV, or TaskNV execution " + << " to be used only with Vertex, MeshNV, TaskNV , MeshEXT or" + << " TaskEXT execution " "model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); @@ -3818,6 +3850,7 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtReference( case SpvExecutionModelVertex: case SpvExecutionModelGeometry: case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: break; default: { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -4276,6 +4309,10 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition( case SpvBuiltInMeshViewCountNV: case SpvBuiltInMeshViewIndicesNV: case SpvBuiltInCurrentRayTimeNV: + case SpvBuiltInPrimitivePointIndicesEXT: + case SpvBuiltInPrimitiveLineIndicesEXT: + case SpvBuiltInPrimitiveTriangleIndicesEXT: + case SpvBuiltInCullPrimitiveEXT: // No validation rules (for the moment). break; diff --git a/source/val/validate_extensions.cpp b/source/val/validate_extensions.cpp index fcf04e207..1e69cb37f 100644 --- a/source/val/validate_extensions.cpp +++ b/source/val/validate_extensions.cpp @@ -756,10 +756,10 @@ spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) { if (_.version() < SPV_SPIRV_VERSION_WORD(1, 4)) { std::string extension = GetExtensionString(&(inst->c_inst())); if (extension == - ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout)) { + ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout) || + extension == ExtensionToString(kSPV_EXT_mesh_shader)) { return _.diag(SPV_ERROR_WRONG_VERSION, inst) - << "SPV_KHR_workgroup_memory_explicit_layout extension " - "requires SPIR-V version 1.4 or later."; + << extension << " extension requires SPIR-V version 1.4 or later."; } } diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp index d4fca84ab..e4ad0e027 100644 --- a/source/val/validate_memory.cpp +++ b/source/val/validate_memory.cpp @@ -442,7 +442,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { storage_class != SpvStorageClassIncomingRayPayloadKHR && storage_class != SpvStorageClassHitAttributeKHR && storage_class != SpvStorageClassCallableDataKHR && - storage_class != SpvStorageClassIncomingCallableDataKHR) { + storage_class != SpvStorageClassIncomingCallableDataKHR && + storage_class != SpvStorageClassTaskPayloadWorkgroupEXT) { bool storage_input_or_output = storage_class == SpvStorageClassInput || storage_class == SpvStorageClassOutput; bool builtin = false; diff --git a/source/val/validate_mode_setting.cpp b/source/val/validate_mode_setting.cpp index 67b10c5ac..09a9d48e1 100644 --- a/source/val/validate_mode_setting.cpp +++ b/source/val/validate_mode_setting.cpp @@ -12,13 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#include "source/val/validate.h" - #include <algorithm> #include "source/opcode.h" #include "source/spirv_target_env.h" #include "source/val/instruction.h" +#include "source/val/validate.h" #include "source/val/validation_state.h" namespace spvtools { @@ -359,14 +358,18 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, return true; case SpvExecutionModelMeshNV: return _.HasCapability(SpvCapabilityMeshShadingNV); + case SpvExecutionModelMeshEXT: + return _.HasCapability( + SpvCapabilityMeshShadingEXT); default: return false; } })) { - if (_.HasCapability(SpvCapabilityMeshShadingNV)) { + if (_.HasCapability(SpvCapabilityMeshShadingNV) || + _.HasCapability(SpvCapabilityMeshShadingEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "Execution mode can only be used with the Geometry or " - "MeshNV execution model."; + << "Execution mode can only be used with the Geometry " + "MeshNV or MeshEXT execution model."; } else { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with the Geometry " @@ -421,14 +424,18 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, return true; case SpvExecutionModelMeshNV: return _.HasCapability(SpvCapabilityMeshShadingNV); + case SpvExecutionModelMeshEXT: + return _.HasCapability( + SpvCapabilityMeshShadingEXT); default: return false; } })) { - if (_.HasCapability(SpvCapabilityMeshShadingNV)) { + if (_.HasCapability(SpvCapabilityMeshShadingNV) || + _.HasCapability(SpvCapabilityMeshShadingEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Geometry, " - "tessellation or MeshNV execution model."; + "tessellation, MeshNV or MeshEXT execution model."; } else { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Geometry or " @@ -494,14 +501,19 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, case SpvExecutionModelTaskNV: case SpvExecutionModelMeshNV: return _.HasCapability(SpvCapabilityMeshShadingNV); + case SpvExecutionModelTaskEXT: + case SpvExecutionModelMeshEXT: + return _.HasCapability( + SpvCapabilityMeshShadingEXT); default: return false; } })) { - if (_.HasCapability(SpvCapabilityMeshShadingNV)) { + if (_.HasCapability(SpvCapabilityMeshShadingNV) || + _.HasCapability(SpvCapabilityMeshShadingEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Kernel, GLCompute, " - "MeshNV, or TaskNV execution model."; + "MeshNV, MeshEXT, TaskNV or TaskEXT execution model."; } else { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Kernel or " diff --git a/source/val/validate_scopes.cpp b/source/val/validate_scopes.cpp index a5f3db14f..5fb661b0d 100644 --- a/source/val/validate_scopes.cpp +++ b/source/val/validate_scopes.cpp @@ -144,14 +144,16 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _, [errorVUID](SpvExecutionModel model, std::string* message) { if (model != SpvExecutionModelTaskNV && model != SpvExecutionModelMeshNV && + model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT && model != SpvExecutionModelTessellationControl && model != SpvExecutionModelGLCompute) { if (message) { *message = errorVUID + "in Vulkan environment, Workgroup execution scope is " - "only for TaskNV, MeshNV, TessellationControl, and " - "GLCompute execution models"; + "only for TaskNV, MeshNV, TaskEXT, MeshEXT, " + "TessellationControl, and GLCompute execution models"; } return false; } @@ -269,11 +271,14 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, [errorVUID](SpvExecutionModel model, std::string* message) { if (model != SpvExecutionModelGLCompute && model != SpvExecutionModelTaskNV && - model != SpvExecutionModelMeshNV) { + model != SpvExecutionModelMeshNV && + model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT) { if (message) { *message = errorVUID + "Workgroup Memory Scope is limited to MeshNV, " - "TaskNV, and GLCompute execution model"; + "TaskNV, MeshEXT, TaskEXT and GLCompute " + "execution model"; } return false; } diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index 3501e8ceb..2e1fa31ae 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -639,7 +639,9 @@ void ValidationState_t::RegisterStorageClassConsumer( std::string* message) { if (model != SpvExecutionModelGLCompute && model != SpvExecutionModelTaskNV && - model != SpvExecutionModelMeshNV) { + model != SpvExecutionModelMeshNV && + model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT) { if (message) { *message = errorVUID + @@ -1522,6 +1524,7 @@ bool ValidationState_t::IsValidStorageClass( case SpvStorageClassCallableDataKHR: case SpvStorageClassIncomingCallableDataKHR: case SpvStorageClassShaderRecordBufferKHR: + case SpvStorageClassTaskPayloadWorkgroupEXT: return true; default: return false; |