From dcb2740ffbba352df7a838998def2bd29fbb69b7 Mon Sep 17 00:00:00 2001 From: gnl21 Date: Thu, 26 Aug 2021 19:33:19 +0100 Subject: [PATCH] Add a feature for allowing LocalSizeId (#4492) Allow LocalSizeId as a way of sizing compute workgroups where the environment allows it. A command-line switch is also added to force acceptance even where the environment would not otherwise allow it. --- include/spirv-tools/libspirv.h | 5 +++++ include/spirv-tools/libspirv.hpp | 6 ++++++ source/spirv_validator_options.cpp | 5 +++++ source/spirv_validator_options.h | 2 ++ source/val/validate_mode_setting.cpp | 11 +++++++++++ source/val/validation_state.cpp | 3 +++ source/val/validation_state.h | 9 +++++++++ tools/val/val.cpp | 4 ++++ 8 files changed, 45 insertions(+) diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h index 999589e2..1cd40cc8 100644 --- a/include/spirv-tools/libspirv.h +++ b/include/spirv-tools/libspirv.h @@ -659,6 +659,11 @@ SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetWorkgroupScalarBlockLayout( SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetSkipBlockLayout( spv_validator_options options, bool val); +// Records whether or not the validator should allow the LocalSizeId +// decoration where the environment otherwise would not allow it. +SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetAllowLocalSizeId( + spv_validator_options options, bool val); + // Creates an optimizer options object with default options. Returns a valid // options object. The object remains valid until it is passed into // |spvOptimizerOptionsDestroy|. diff --git a/include/spirv-tools/libspirv.hpp b/include/spirv-tools/libspirv.hpp index 0c31a182..8dfb46b7 100644 --- a/include/spirv-tools/libspirv.hpp +++ b/include/spirv-tools/libspirv.hpp @@ -115,6 +115,12 @@ class ValidatorOptions { spvValidatorOptionsSetSkipBlockLayout(options_, val); } + // Enables LocalSizeId decorations where the environment would not otherwise + // allow them. + void SetAllowLocalSizeId(bool val) { + spvValidatorOptionsSetAllowLocalSizeId(options_, val); + } + // Records whether or not the validator should relax the rules on pointer // usage in logical addressing mode. // diff --git a/source/spirv_validator_options.cpp b/source/spirv_validator_options.cpp index 2716cca9..e5b1eece 100644 --- a/source/spirv_validator_options.cpp +++ b/source/spirv_validator_options.cpp @@ -120,3 +120,8 @@ void spvValidatorOptionsSetSkipBlockLayout(spv_validator_options options, bool val) { options->skip_block_layout = val; } + +void spvValidatorOptionsSetAllowLocalSizeId(spv_validator_options options, + bool val) { + options->allow_localsizeid = val; +} diff --git a/source/spirv_validator_options.h b/source/spirv_validator_options.h index baaa5359..a357c031 100644 --- a/source/spirv_validator_options.h +++ b/source/spirv_validator_options.h @@ -47,6 +47,7 @@ struct spv_validator_options_t { scalar_block_layout(false), workgroup_scalar_block_layout(false), skip_block_layout(false), + allow_localsizeid(false), before_hlsl_legalization(false) {} validator_universal_limits_t universal_limits_; @@ -57,6 +58,7 @@ struct spv_validator_options_t { bool scalar_block_layout; bool workgroup_scalar_block_layout; bool skip_block_layout; + bool allow_localsizeid; bool before_hlsl_legalization; }; diff --git a/source/val/validate_mode_setting.cpp b/source/val/validate_mode_setting.cpp index 79f82d8d..4fb6d9b9 100644 --- a/source/val/validate_mode_setting.cpp +++ b/source/val/validate_mode_setting.cpp @@ -225,6 +225,13 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) { } } } + if (i.opcode() == SpvOpExecutionModeId) { + const auto mode = i.GetOperandAs(1); + if (mode == SpvExecutionModeLocalSizeId) { + ok = true; + break; + } + } } if (!ok) { return _.diag(SPV_ERROR_INVALID_DATA, inst) @@ -429,6 +436,10 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, break; case SpvExecutionModeLocalSize: case SpvExecutionModeLocalSizeId: + if (mode == SpvExecutionModeLocalSizeId && !_.IsLocalSizeIdAllowed()) + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "LocalSizeId mode is not allowed by the current environment."; + if (!std::all_of(models->begin(), models->end(), [&_](const SpvExecutionModel& model) { switch (model) { diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index c9ac3ae7..e6a02dc9 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -175,6 +175,9 @@ ValidationState_t::ValidationState_t(const spv_const_context ctx, } } + // LocalSizeId is always allowed in non-Vulkan environments. + features_.env_allow_localsizeid = !spvIsVulkanEnv(env); + // Only attempt to count if we have words, otherwise let the other validation // fail and generate an error. if (num_words > 0) { diff --git a/source/val/validation_state.h b/source/val/validation_state.h index 2fe96621..4e35cd2e 100644 --- a/source/val/validation_state.h +++ b/source/val/validation_state.h @@ -121,6 +121,9 @@ class ValidationState_t { // SPIR-V 1.4 allows Function and Private variables to be NonWritable bool nonwritable_var_in_function_or_private = false; + + // Whether LocalSizeId execution mode is allowed by the environment. + bool env_allow_localsizeid = false; }; ValidationState_t(const spv_const_context context, @@ -493,6 +496,12 @@ class ValidationState_t { return features_.env_relaxed_block_layout || options()->relax_block_layout; } + // Returns true if allowing localsizeid, either because the environment always + // allows it, or because it is enabled from the command-line. + bool IsLocalSizeIdAllowed() const { + return features_.env_allow_localsizeid || options()->allow_localsizeid; + } + /// Sets the struct nesting depth for a given struct ID void set_struct_nesting_depth(uint32_t id, uint32_t depth) { struct_nesting_depth_[id] = depth; diff --git a/tools/val/val.cpp b/tools/val/val.cpp index 21a7d8f4..55321dab 100644 --- a/tools/val/val.cpp +++ b/tools/val/val.cpp @@ -64,6 +64,8 @@ Options: --relax-struct-store Allow store from one struct type to a different type with compatible layout and members. + --allow-localsizeid Allow use of the LocalSizeId decoration where it would otherwise not + be allowed by the target environment. --before-hlsl-legalization Allows code patterns that are intended to be fixed by spirv-opt's legalization passes. --version Display validator version information. @@ -153,6 +155,8 @@ int main(int argc, char** argv) { options.SetWorkgroupScalarBlockLayout(true); } else if (0 == strcmp(cur_arg, "--skip-block-layout")) { options.SetSkipBlockLayout(true); + } else if (0 == strcmp(cur_arg, "--allow-localsizeid")) { + options.SetAllowLocalSizeId(true); } else if (0 == strcmp(cur_arg, "--relax-struct-store")) { options.SetRelaxStructStore(true); } else if (0 == cur_arg[1]) {