From 5d786f6cc74ccb971fdb2213822e4a72b9827024 Mon Sep 17 00:00:00 2001 From: David Neto Date: Fri, 24 Jan 2020 16:26:07 -0500 Subject: [PATCH] Clarify mapping of target env to SPIR-V version (#3150) * Clarify mapping of target env to SPIR-V version It depends on the API method. * Update SPIR-V version comments on validator --- include/spirv-tools/libspirv.h | 36 ++++++++++++++++++++++++++++--- include/spirv-tools/libspirv.hpp | 25 ++++++++++++++++++++- include/spirv-tools/optimizer.hpp | 27 ++++++++++++++++++----- 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h index f6af78ff..d63f3634 100644 --- a/include/spirv-tools/libspirv.h +++ b/include/spirv-tools/libspirv.h @@ -419,8 +419,17 @@ SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionString(void); SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionDetailsString(void); // Certain target environments impose additional restrictions on SPIR-V, so it's -// often necessary to specify which one applies. SPV_ENV_UNIVERSAL means +// often necessary to specify which one applies. SPV_ENV_UNIVERSAL_* implies an // environment-agnostic SPIR-V. +// +// When an API method needs to derive a SPIR-V version from a target environment +// (from the spv_context object), the method will choose the highest version of +// SPIR-V supported by the target environment. Examples: +// SPV_ENV_VULKAN_1_0 -> SPIR-V 1.0 +// SPV_ENV_VULKAN_1_1 -> SPIR-V 1.3 +// SPV_ENV_VULKAN_1_1_SPIRV_1_4 -> SPIR-V 1.4 +// SPV_ENV_VULKAN_1_2 -> SPIR-V 1.5 +// Consult the description of API entry points for specific rules. typedef enum { SPV_ENV_UNIVERSAL_1_0, // SPIR-V 1.0 latest revision, no other restrictions. SPV_ENV_VULKAN_1_0, // Vulkan 1.0 latest revision. @@ -448,7 +457,10 @@ typedef enum { SPV_ENV_VULKAN_1_1, // Vulkan 1.1 latest revision. SPV_ENV_WEBGPU_0, // Work in progress WebGPU 1.0. SPV_ENV_UNIVERSAL_1_4, // SPIR-V 1.4 latest revision, no other restrictions. - SPV_ENV_VULKAN_1_1_SPIRV_1_4, // Vulkan 1.1 with SPIR-V 1.4 binary. + + // Vulkan 1.1 with VK_KHR_spirv_1_4, i.e. SPIR-V 1.4 binary. + SPV_ENV_VULKAN_1_1_SPIRV_1_4, + SPV_ENV_UNIVERSAL_1_5, // SPIR-V 1.5 latest revision, no other restrictions. SPV_ENV_VULKAN_1_2, // Vulkan 1.2 latest revision. } spv_target_env; @@ -486,7 +498,11 @@ SPIRV_TOOLS_EXPORT bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver, spv_target_env* env); -// Creates a context object. Returns null if env is invalid. +// Creates a context object for most of the SPIRV-Tools API. +// Returns null if env is invalid. +// +// See specific API calls for how the target environment is interpeted +// (particularly assembly and validation). SPIRV_TOOLS_EXPORT spv_context spvContextCreate(spv_target_env env); // Destroys the given context object. @@ -667,6 +683,8 @@ SPIRV_TOOLS_EXPORT void spvFuzzerOptionsEnableFuzzerPassValidation( // be stored into *binary. Any error will be written into *diagnostic if // diagnostic is non-null, otherwise the context's message consumer will be // used. The generated binary is independent of the context and may outlive it. +// The SPIR-V binary version is set to the highest version of SPIR-V supported +// by the context's target environment. SPIRV_TOOLS_EXPORT spv_result_t spvTextToBinary(const spv_const_context context, const char* text, const size_t length, @@ -704,6 +722,12 @@ SPIRV_TOOLS_EXPORT void spvBinaryDestroy(spv_binary binary); // Validates a SPIR-V binary for correctness. Any errors will be written into // *diagnostic if diagnostic is non-null, otherwise the context's message // consumer will be used. +// +// Validate for SPIR-V spec rules for the SPIR-V version named in the +// binary's header (at word offset 1). Additionally, if the context target +// environment is a client API (such as Vulkan 1.1), then validate for that +// client API version, to the extent that it is verifiable from data in the +// binary itself. SPIRV_TOOLS_EXPORT spv_result_t spvValidate(const spv_const_context context, const spv_const_binary binary, spv_diagnostic* diagnostic); @@ -711,6 +735,12 @@ SPIRV_TOOLS_EXPORT spv_result_t spvValidate(const spv_const_context context, // Validates a SPIR-V binary for correctness. Uses the provided Validator // options. Any errors will be written into *diagnostic if diagnostic is // non-null, otherwise the context's message consumer will be used. +// +// Validate for SPIR-V spec rules for the SPIR-V version named in the +// binary's header (at word offset 1). Additionally, if the context target +// environment is a client API (such as Vulkan 1.1), then validate for that +// client API version, to the extent that it is verifiable from data in the +// binary itself, or in the validator options. SPIRV_TOOLS_EXPORT spv_result_t spvValidateWithOptions( const spv_const_context context, const spv_const_validator_options options, const spv_const_binary binary, spv_diagnostic* diagnostic); diff --git a/include/spirv-tools/libspirv.hpp b/include/spirv-tools/libspirv.hpp index ceadef8f..5e1819ee 100644 --- a/include/spirv-tools/libspirv.hpp +++ b/include/spirv-tools/libspirv.hpp @@ -36,6 +36,9 @@ class Context { public: // Constructs a context targeting the given environment |env|. // + // See specific API calls for how the target environment is interpeted + // (particularly assembly and validation). + // // The constructed instance will have an empty message consumer, which just // ignores all messages from the library. Use SetMessageConsumer() to supply // one if messages are of concern. @@ -279,16 +282,20 @@ class SpirvTools { // Assembles the given assembly |text| and writes the result to |binary|. // Returns true on successful assembling. |binary| will be kept untouched if // assembling is unsuccessful. + // The SPIR-V binary version is set to the highest version of SPIR-V supported + // by the target environment with which this SpirvTools object was created. bool Assemble(const std::string& text, std::vector* binary, uint32_t options = kDefaultAssembleOption) const; // |text_size| specifies the number of bytes in |text|. A terminating null // character is not required to present in |text| as long as |text| is valid. + // The SPIR-V binary version is set to the highest version of SPIR-V supported + // by the target environment with which this SpirvTools object was created. bool Assemble(const char* text, size_t text_size, std::vector* binary, uint32_t options = kDefaultAssembleOption) const; // Disassembles the given SPIR-V |binary| with the given |options| and writes - // the assembly to |text|. Returns ture on successful disassembling. |text| + // the assembly to |text|. Returns true on successful disassembling. |text| // will be kept untouched if diassembling is unsuccessful. bool Disassemble(const std::vector& binary, std::string* text, uint32_t options = kDefaultDisassembleOption) const; @@ -300,10 +307,26 @@ class SpirvTools { // Validates the given SPIR-V |binary|. Returns true if no issues are found. // Otherwise, returns false and communicates issues via the message consumer // registered. + // Validates for SPIR-V spec rules for the SPIR-V version named in the + // binary's header (at word offset 1). Additionally, if the target + // environment is a client API (such as Vulkan 1.1), then validate for that + // client API version, to the extent that it is verifiable from data in the + // binary itself. bool Validate(const std::vector& binary) const; + // Like the previous overload, but provides the binary as a pointer and size: // |binary_size| specifies the number of words in |binary|. + // Validates for SPIR-V spec rules for the SPIR-V version named in the + // binary's header (at word offset 1). Additionally, if the target + // environment is a client API (such as Vulkan 1.1), then validate for that + // client API version, to the extent that it is verifiable from data in the + // binary itself. bool Validate(const uint32_t* binary, size_t binary_size) const; // Like the previous overload, but takes an options object. + // Validates for SPIR-V spec rules for the SPIR-V version named in the + // binary's header (at word offset 1). Additionally, if the target + // environment is a client API (such as Vulkan 1.1), then validate for that + // client API version, to the extent that it is verifiable from data in the + // binary itself, or in the validator options. bool Validate(const uint32_t* binary, size_t binary_size, spv_validator_options options) const; diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp index ba8cbaf0..c31ccef8 100644 --- a/include/spirv-tools/optimizer.hpp +++ b/include/spirv-tools/optimizer.hpp @@ -65,9 +65,9 @@ class Optimizer { // Constructs an instance with the given target |env|, which is used to decode // the binaries to be optimized later. // - // The constructed instance will have an empty message consumer, which just - // ignores all messages from the library. Use SetMessageConsumer() to supply - // one if messages are of concern. + // The instance will have an empty message consumer, which ignores all + // messages from the library. Use SetMessageConsumer() to supply a consumer + // if messages are of concern. // // For collections of passes that are meant to transform the input into // another execution environment, then the source environment should be @@ -164,17 +164,26 @@ class Optimizer { bool FlagHasValidForm(const std::string& flag) const; // Allows changing, after creation time, the target environment to be - // optimized for. Should be called before calling Run(). + // optimized for and validated. Should be called before calling Run(). void SetTargetEnv(const spv_target_env env); // Optimizes the given SPIR-V module |original_binary| and writes the - // optimized binary into |optimized_binary|. + // optimized binary into |optimized_binary|. The optimized binary uses + // the same SPIR-V version as the original binary. + // // Returns true on successful optimization, whether or not the module is // modified. Returns false if |original_binary| fails to validate or if errors // occur when processing |original_binary| using any of the registered passes. // In that case, no further passes are executed and the contents in // |optimized_binary| may be invalid. // + // By default, the binary is validated before any transforms are performed, + // and optionally after each transform. Validation uses SPIR-V spec rules + // for the SPIR-V version named in the binary's header (at word offset 1). + // Additionally, if the target environment is a client API (such as + // Vulkan 1.1), then validate for that client API version, to the extent + // that it is verifiable from data in the binary itself. + // // It's allowed to alias |original_binary| to the start of |optimized_binary|. bool Run(const uint32_t* original_binary, size_t original_binary_size, std::vector* optimized_binary) const; @@ -190,6 +199,14 @@ class Optimizer { // Same as above, except it takes an options object. See the documentation // for |OptimizerOptions| to see which options can be set. + // + // By default, the binary is validated before any transforms are performed, + // and optionally after each transform. Validation uses SPIR-V spec rules + // for the SPIR-V version named in the binary's header (at word offset 1). + // Additionally, if the target environment is a client API (such as + // Vulkan 1.1), then validate for that client API version, to the extent + // that it is verifiable from data in the binary itself, or from the + // validator options set on the optimizer options. bool Run(const uint32_t* original_binary, const size_t original_binary_size, std::vector* optimized_binary, const spv_optimizer_options opt_options) const;