From a867d872f420fd76aa7f77e34f882576a84cc4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Fri, 15 Jan 2021 20:33:45 -0800 Subject: [PATCH] Updated spirv-tools. --- 3rdparty/spirv-tools/README.md | 1 - .../include/generated/build-version.inc | 2 +- .../include/spirv-tools/libspirv.h | 2 +- .../include/spirv-tools/optimizer.hpp | 41 ----- 3rdparty/spirv-tools/source/ext_inst.cpp | 1 - 3rdparty/spirv-tools/source/libspirv.cpp | 6 +- 3rdparty/spirv-tools/source/link/linker.cpp | 5 +- .../spirv-tools/source/opt/CMakeLists.txt | 9 - .../decompose_initialized_variables_pass.cpp | 112 ------------- .../decompose_initialized_variables_pass.h | 57 ------- .../opt/generate_webgpu_initializers_pass.cpp | 116 ------------- .../opt/generate_webgpu_initializers_pass.h | 62 ------- 3rdparty/spirv-tools/source/opt/ir_loader.cpp | 9 +- .../opt/legalize_vector_shuffle_pass.cpp | 39 ----- .../source/opt/legalize_vector_shuffle_pass.h | 53 ------ 3rdparty/spirv-tools/source/opt/module.h | 14 +- 3rdparty/spirv-tools/source/opt/optimizer.cpp | 64 +------- 3rdparty/spirv-tools/source/opt/passes.h | 5 - .../opt/split_invalid_unreachable_pass.cpp | 95 ----------- .../opt/split_invalid_unreachable_pass.h | 51 ------ .../opt/strip_atomic_counter_memory_pass.cpp | 57 ------- .../opt/strip_atomic_counter_memory_pass.h | 51 ------ .../spirv-tools/source/spirv_target_env.cpp | 61 ++----- .../spirv-tools/source/spirv_target_env.h | 8 +- 3rdparty/spirv-tools/source/table.cpp | 1 - 3rdparty/spirv-tools/source/val/validate.cpp | 77 +-------- .../source/val/validate_annotation.cpp | 63 ------- .../source/val/validate_atomics.cpp | 14 +- .../source/val/validate_builtins.cpp | 154 +++--------------- .../source/val/validate_capability.cpp | 21 --- .../spirv-tools/source/val/validate_cfg.cpp | 121 -------------- .../source/val/validate_composites.cpp | 8 - .../source/val/validate_extensions.cpp | 26 --- .../spirv-tools/source/val/validate_image.cpp | 11 +- .../source/val/validate_memory.cpp | 53 +----- .../source/val/validate_memory_semantics.cpp | 49 ------ .../spirv-tools/source/val/validate_misc.cpp | 4 - .../source/val/validate_mode_setting.cpp | 31 +--- .../source/val/validate_scopes.cpp | 80 --------- .../spirv-tools/source/val/validate_type.cpp | 33 +--- .../source/val/validation_state.cpp | 21 +-- 41 files changed, 108 insertions(+), 1580 deletions(-) delete mode 100644 3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.cpp delete mode 100644 3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.h delete mode 100644 3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.cpp delete mode 100644 3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.h delete mode 100644 3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.cpp delete mode 100644 3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.h delete mode 100644 3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.cpp delete mode 100644 3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.h delete mode 100644 3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp delete mode 100644 3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h diff --git a/3rdparty/spirv-tools/README.md b/3rdparty/spirv-tools/README.md index 44f582fb8..3637305ba 100644 --- a/3rdparty/spirv-tools/README.md +++ b/3rdparty/spirv-tools/README.md @@ -136,7 +136,6 @@ As of this writing, there are 67 transforms including examples such as: * Loop-invariant code motion * Loop unroll * Other - * Generate WebGPU initializers * Graphics robust access * Upgrade memory model to VulkanKHR diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index 88a2834d1..784311bd2 100644 --- a/3rdparty/spirv-tools/include/generated/build-version.inc +++ b/3rdparty/spirv-tools/include/generated/build-version.inc @@ -1 +1 @@ -"v2020.7-dev", "SPIRV-Tools v2020.7-dev d4fbcb113c0231d993c0ca500abfc16459fce47a" +"v2020.7-dev", "SPIRV-Tools v2020.7-dev 630263d1cbcdda5c28b5b80730ad90ce0b3b6e90" diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h index a441d3573..9313ea50d 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h +++ b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h @@ -483,7 +483,7 @@ typedef enum { SPV_ENV_OPENCL_EMBEDDED_2_2, // OpenCL Embedded Profile 2.2 latest revision. SPV_ENV_UNIVERSAL_1_3, // SPIR-V 1.3 latest revision, no other restrictions. SPV_ENV_VULKAN_1_1, // Vulkan 1.1 latest revision. - SPV_ENV_WEBGPU_0, // Work in progress WebGPU 1.0. + SPV_ENV_WEBGPU_0, // DEPRECATED, may be removed in the future. SPV_ENV_UNIVERSAL_1_4, // SPIR-V 1.4 latest revision, no other restrictions. // Vulkan 1.1 with VK_KHR_spirv_1_4, i.e. SPIR-V 1.4 binary. diff --git a/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp b/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp index 27352b250..1683d077f 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp +++ b/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp @@ -68,11 +68,6 @@ class Optimizer { // 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 - // supplied. e.g. for VulkanToWebGPUPasses the environment should be - // SPV_ENV_VULKAN_1_1 not SPV_ENV_WEBGPU_0. explicit Optimizer(spv_target_env env); // Disables copy/move constructor/assignment operations. @@ -106,16 +101,6 @@ class Optimizer { // from time to time. Optimizer& RegisterSizePasses(); - // Registers passes that have been prescribed for converting from Vulkan to - // WebGPU. This sequence of passes is subject to constant review and will - // change from time to time. - Optimizer& RegisterVulkanToWebGPUPasses(); - - // Registers passes that have been prescribed for converting from WebGPU to - // Vulkan. This sequence of passes is subject to constant review and will - // change from time to time. - Optimizer& RegisterWebGPUToVulkanPasses(); - // Registers passes that attempt to legalize the generated code. // // Note: this recipe is specially designed for legalizing SPIR-V. It should be @@ -238,13 +223,6 @@ class Optimizer { // A null pass does nothing to the SPIR-V module to be optimized. Optimizer::PassToken CreateNullPass(); -// Creates a strip-atomic-counter-memory pass. -// A strip-atomic-counter-memory pass removes all usages of the -// AtomicCounterMemory bit in Memory Semantics bitmasks. This bit is a no-op in -// Vulkan, so isn't needed in that env. And the related capability is not -// allowed in WebGPU, so it is not allowed in that env. -Optimizer::PassToken CreateStripAtomicCounterMemoryPass(); - // Creates a strip-debug-info pass. // A strip-debug-info pass removes all debug instructions (as documented in // Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized. @@ -802,30 +780,11 @@ Optimizer::PassToken CreateUpgradeMemoryModelPass(); // where an instruction is moved into a more deeply nested construct. Optimizer::PassToken CreateCodeSinkingPass(); -// Create a pass to adds initializers for OpVariable calls that require them -// in WebGPU. Currently this pass naively initializes variables that are -// missing an initializer with a null value. In the future it may initialize -// variables to the first value stored in them, if that is a constant. -Optimizer::PassToken CreateGenerateWebGPUInitializersPass(); - // Create a pass to fix incorrect storage classes. In order to make code // generation simpler, DXC may generate code where the storage classes do not // match up correctly. This pass will fix the errors that it can. Optimizer::PassToken CreateFixStorageClassPass(); -// Create a pass to legalize OpVectorShuffle operands going into WebGPU. WebGPU -// forbids using 0xFFFFFFFF, which indicates an undefined result, so this pass -// converts those literals to 0. -Optimizer::PassToken CreateLegalizeVectorShufflePass(); - -// Create a pass to decompose initialized variables into a seperate variable -// declaration and an initial store. -Optimizer::PassToken CreateDecomposeInitializedVariablesPass(); - -// Create a pass to attempt to split up invalid unreachable merge-blocks and -// continue-targets to legalize for WebGPU. -Optimizer::PassToken CreateSplitInvalidUnreachablePass(); - // Creates a graphics robust access pass. // // This pass injects code to clamp indexed accesses to buffers and internal diff --git a/3rdparty/spirv-tools/source/ext_inst.cpp b/3rdparty/spirv-tools/source/ext_inst.cpp index 3471ebe0d..795cb0f3f 100644 --- a/3rdparty/spirv-tools/source/ext_inst.cpp +++ b/3rdparty/spirv-tools/source/ext_inst.cpp @@ -89,7 +89,6 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable, case SPV_ENV_UNIVERSAL_1_3: case SPV_ENV_VULKAN_1_1: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: - case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_UNIVERSAL_1_5: case SPV_ENV_VULKAN_1_2: diff --git a/3rdparty/spirv-tools/source/libspirv.cpp b/3rdparty/spirv-tools/source/libspirv.cpp index a1ed11d3f..0bc093508 100644 --- a/3rdparty/spirv-tools/source/libspirv.cpp +++ b/3rdparty/spirv-tools/source/libspirv.cpp @@ -14,8 +14,8 @@ #include "spirv-tools/libspirv.hpp" +#include #include - #include #include #include @@ -60,7 +60,9 @@ struct SpirvTools::Impl { spv_context context; // C interface context object. }; -SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) {} +SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) { + assert(env != SPV_ENV_WEBGPU_0); +} SpirvTools::~SpirvTools() {} diff --git a/3rdparty/spirv-tools/source/link/linker.cpp b/3rdparty/spirv-tools/source/link/linker.cpp index da6f0a78c..8da4a98d8 100644 --- a/3rdparty/spirv-tools/source/link/linker.cpp +++ b/3rdparty/spirv-tools/source/link/linker.cpp @@ -676,14 +676,15 @@ spv_result_t Link(const Context& context, const uint32_t* const* binaries, if (schema != 0u) { position.index = 4u; return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY) - << "Schema is non-zero for module " << i << "."; + << "Schema is non-zero for module " << i + 1 << "."; } std::unique_ptr ir_context = BuildModule( c_context->target_env, consumer, binaries[i], binary_sizes[i]); if (ir_context == nullptr) return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY) - << "Failed to build a module out of " << ir_contexts.size() << "."; + << "Failed to build module " << i + 1 << " out of " << num_binaries + << "."; modules.push_back(ir_context->module()); ir_contexts.push_back(std::move(ir_context)); } diff --git a/3rdparty/spirv-tools/source/opt/CMakeLists.txt b/3rdparty/spirv-tools/source/opt/CMakeLists.txt index f3ac59060..14a6bee7d 100644 --- a/3rdparty/spirv-tools/source/opt/CMakeLists.txt +++ b/3rdparty/spirv-tools/source/opt/CMakeLists.txt @@ -32,7 +32,6 @@ set(SPIRV_TOOLS_OPT_SOURCES dead_branch_elim_pass.h dead_insert_elim_pass.h dead_variable_elimination.h - decompose_initialized_variables_pass.h decoration_manager.h debug_info_manager.h def_use_manager.h @@ -52,7 +51,6 @@ set(SPIRV_TOOLS_OPT_SOURCES fold_spec_constant_op_and_composite_pass.h freeze_spec_constant_value_pass.h function.h - generate_webgpu_initializers_pass.h graphics_robust_access_pass.h if_conversion.h inline_exhaustive_pass.h @@ -103,10 +101,8 @@ set(SPIRV_TOOLS_OPT_SOURCES scalar_replacement_pass.h set_spec_constant_default_value_pass.h simplification_pass.h - split_invalid_unreachable_pass.h ssa_rewrite_pass.h strength_reduction_pass.h - strip_atomic_counter_memory_pass.h strip_debug_info_pass.h strip_reflect_info_pass.h struct_cfg_analysis.h @@ -140,7 +136,6 @@ set(SPIRV_TOOLS_OPT_SOURCES dead_branch_elim_pass.cpp dead_insert_elim_pass.cpp dead_variable_elimination.cpp - decompose_initialized_variables_pass.cpp decoration_manager.cpp debug_info_manager.cpp def_use_manager.cpp @@ -160,7 +155,6 @@ set(SPIRV_TOOLS_OPT_SOURCES freeze_spec_constant_value_pass.cpp function.cpp graphics_robust_access_pass.cpp - generate_webgpu_initializers_pass.cpp if_conversion.cpp inline_exhaustive_pass.cpp inline_opaque_pass.cpp @@ -173,7 +167,6 @@ set(SPIRV_TOOLS_OPT_SOURCES instrument_pass.cpp ir_context.cpp ir_loader.cpp - legalize_vector_shuffle_pass.cpp licm_pass.cpp local_access_chain_convert_pass.cpp local_redundancy_elimination.cpp @@ -208,10 +201,8 @@ set(SPIRV_TOOLS_OPT_SOURCES scalar_replacement_pass.cpp set_spec_constant_default_value_pass.cpp simplification_pass.cpp - split_invalid_unreachable_pass.cpp ssa_rewrite_pass.cpp strength_reduction_pass.cpp - strip_atomic_counter_memory_pass.cpp strip_debug_info_pass.cpp strip_reflect_info_pass.cpp struct_cfg_analysis.cpp diff --git a/3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.cpp b/3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.cpp deleted file mode 100644 index 875bf7e85..000000000 --- a/3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "source/opt/decompose_initialized_variables_pass.h" - -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { - -using inst_iterator = InstructionList::iterator; - -namespace { - -bool HasInitializer(Instruction* inst) { - if (inst->opcode() != SpvOpVariable) return false; - if (inst->NumOperands() < 4) return false; - - return true; -} - -} // namespace - -Pass::Status DecomposeInitializedVariablesPass::Process() { - auto* module = context()->module(); - std::unordered_set changed; - - std::vector> global_stores; - for (auto iter = module->types_values_begin(); - iter != module->types_values_end(); ++iter) { - Instruction* inst = &(*iter); - if (!HasInitializer(inst)) continue; - - auto var_id = inst->result_id(); - auto val_id = inst->GetOperand(3).words[0]; - global_stores.push_back(std::make_tuple(var_id, val_id)); - iter->RemoveOperand(3); - changed.insert(&*iter); - } - - std::unordered_set entry_ids; - for (auto entry = module->entry_points().begin(); - entry != module->entry_points().end(); ++entry) { - entry_ids.insert(entry->GetSingleWordInOperand(1)); - } - - for (auto func = module->begin(); func != module->end(); ++func) { - std::vector function_stores; - auto first_block = func->entry().get(); - inst_iterator insert_point = first_block->begin(); - for (auto iter = first_block->begin(); - iter != first_block->end() && iter->opcode() == SpvOpVariable; - ++iter) { - // For valid SPIRV-V, there is guaranteed to be at least one instruction - // after the OpVariable instructions. - insert_point = (*iter).NextNode(); - Instruction* inst = &(*iter); - if (!HasInitializer(inst)) continue; - - auto var_id = inst->result_id(); - auto val_id = inst->GetOperand(3).words[0]; - Instruction* store_inst = new Instruction( - context(), SpvOpStore, 0, 0, - {{SPV_OPERAND_TYPE_ID, {var_id}}, {SPV_OPERAND_TYPE_ID, {val_id}}}); - function_stores.push_back(store_inst); - iter->RemoveOperand(3); - changed.insert(&*iter); - } - - if (entry_ids.find(func->result_id()) != entry_ids.end()) { - for (auto store_ids : global_stores) { - uint32_t var_id; - uint32_t val_id; - std::tie(var_id, val_id) = store_ids; - auto* store_inst = new Instruction( - context(), SpvOpStore, 0, 0, - {{SPV_OPERAND_TYPE_ID, {var_id}}, {SPV_OPERAND_TYPE_ID, {val_id}}}); - context()->set_instr_block(store_inst, &*first_block); - first_block->AddInstruction(std::unique_ptr(store_inst)); - store_inst->InsertBefore(&*insert_point); - changed.insert(store_inst); - } - } - - for (auto store = function_stores.begin(); store != function_stores.end(); - ++store) { - context()->set_instr_block(*store, first_block); - (*store)->InsertBefore(&*insert_point); - changed.insert(*store); - } - } - - auto* def_use_mgr = get_def_use_mgr(); - for (auto* inst : changed) def_use_mgr->UpdateDefUse(inst); - - return !changed.empty() ? Pass::Status::SuccessWithChange - : Pass::Status::SuccessWithoutChange; -} - -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.h b/3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.h deleted file mode 100644 index c0bd35e76..000000000 --- a/3rdparty/spirv-tools/source/opt/decompose_initialized_variables_pass.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SOURCE_OPT_DECOMPOSE_INITALIZED_VAIRABLES_PASS_H_ -#define SOURCE_OPT_DECOMPOSE_INITALIZED_VAIRABLES_PASS_H_ - -#include "source/opt/ir_context.h" -#include "source/opt/module.h" -#include "source/opt/pass.h" - -namespace spvtools { -namespace opt { - -// Converts variable declartions with initializers into seperate declaration and -// assignment statements. This is done due to known issues with some Vulkan -// implementations' handling of initialized variables. -// -// Only decomposes variables with storage classes that are valid in Vulkan -// execution environments; Output, Private, and Function. -// Currently only Function is implemented. -class DecomposeInitializedVariablesPass : public Pass { - public: - const char* name() const override { - return "decompose-initialized-variables"; - } - Status Process() override; - - IRContext::Analysis GetPreservedAnalyses() override { - return IRContext::kAnalysisInstrToBlockMapping | - IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | - IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | - IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap | - IRContext::kAnalysisScalarEvolution | - IRContext::kAnalysisRegisterPressure | - IRContext::kAnalysisValueNumberTable | - IRContext::kAnalysisStructuredCFG | - IRContext::kAnalysisBuiltinVarId | - IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes | - IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants; - } -}; - -} // namespace opt -} // namespace spvtools - -#endif // SOURCE_OPT_DECOMPOSE_INITALIZED_VAIRABLES_PASS_H_ diff --git a/3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.cpp b/3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.cpp deleted file mode 100644 index eaed3c28e..000000000 --- a/3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "source/opt/generate_webgpu_initializers_pass.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { - -using inst_iterator = InstructionList::iterator; - -namespace { - -bool NeedsWebGPUInitializer(Instruction* inst) { - if (inst->opcode() != SpvOpVariable) return false; - - auto storage_class = inst->GetSingleWordOperand(2); - if (storage_class != SpvStorageClassOutput && - storage_class != SpvStorageClassPrivate && - storage_class != SpvStorageClassFunction) { - return false; - } - - if (inst->NumOperands() > 3) return false; - - return true; -} - -} // namespace - -Pass::Status GenerateWebGPUInitializersPass::Process() { - auto* module = context()->module(); - bool changed = false; - - // Handle global/module scoped variables - for (auto iter = module->types_values_begin(); - iter != module->types_values_end(); ++iter) { - Instruction* inst = &(*iter); - - if (inst->opcode() == SpvOpConstantNull) { - null_constant_type_map_[inst->type_id()] = inst; - seen_null_constants_.insert(inst); - continue; - } - - if (!NeedsWebGPUInitializer(inst)) continue; - - changed = true; - - auto* constant_inst = GetNullConstantForVariable(inst); - if (!constant_inst) return Status::Failure; - - if (seen_null_constants_.find(constant_inst) == - seen_null_constants_.end()) { - constant_inst->InsertBefore(inst); - null_constant_type_map_[inst->type_id()] = inst; - seen_null_constants_.insert(inst); - } - AddNullInitializerToVariable(constant_inst, inst); - } - - // Handle local/function scoped variables - for (auto func = module->begin(); func != module->end(); ++func) { - auto block = func->entry().get(); - for (auto iter = block->begin(); - iter != block->end() && iter->opcode() == SpvOpVariable; ++iter) { - Instruction* inst = &(*iter); - if (!NeedsWebGPUInitializer(inst)) continue; - - changed = true; - auto* constant_inst = GetNullConstantForVariable(inst); - if (!constant_inst) return Status::Failure; - - AddNullInitializerToVariable(constant_inst, inst); - } - } - - return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange; -} - -Instruction* GenerateWebGPUInitializersPass::GetNullConstantForVariable( - Instruction* variable_inst) { - auto constant_mgr = context()->get_constant_mgr(); - auto* def_use_mgr = get_def_use_mgr(); - - auto* ptr_inst = def_use_mgr->GetDef(variable_inst->type_id()); - auto type_id = ptr_inst->GetInOperand(1).words[0]; - if (null_constant_type_map_.find(type_id) == null_constant_type_map_.end()) { - auto* constant_type = context()->get_type_mgr()->GetType(type_id); - auto* constant = constant_mgr->GetConstant(constant_type, {}); - return constant_mgr->GetDefiningInstruction(constant, type_id); - } else { - return null_constant_type_map_[type_id]; - } -} - -void GenerateWebGPUInitializersPass::AddNullInitializerToVariable( - Instruction* constant_inst, Instruction* variable_inst) { - auto constant_id = constant_inst->result_id(); - variable_inst->AddOperand(Operand(SPV_OPERAND_TYPE_ID, {constant_id})); - get_def_use_mgr()->AnalyzeInstUse(variable_inst); -} - -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.h b/3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.h deleted file mode 100644 index f95e84c5b..000000000 --- a/3rdparty/spirv-tools/source/opt/generate_webgpu_initializers_pass.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SOURCE_OPT_GENERATE_WEBGPU_INITIALIZERS_PASS_H_ -#define SOURCE_OPT_GENERATE_WEBGPU_INITIALIZERS_PASS_H_ - -#include "source/opt/ir_context.h" -#include "source/opt/module.h" -#include "source/opt/pass.h" - -namespace spvtools { -namespace opt { - -// Adds initializers to variables with storage classes Output, Private, and -// Function if they are missing. In the WebGPU environment these storage classes -// require that the variables are initialized. Currently they are initialized to -// NULL, though in the future some of them may be initialized to the first value -// that is stored in them, if that was a constant. -class GenerateWebGPUInitializersPass : public Pass { - public: - const char* name() const override { return "generate-webgpu-initializers"; } - Status Process() override; - - IRContext::Analysis GetPreservedAnalyses() override { - return IRContext::kAnalysisInstrToBlockMapping | - IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | - IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | - IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap | - IRContext::kAnalysisScalarEvolution | - IRContext::kAnalysisRegisterPressure | - IRContext::kAnalysisValueNumberTable | - IRContext::kAnalysisStructuredCFG | - IRContext::kAnalysisBuiltinVarId | - IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes | - IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants; - } - - private: - using NullConstantTypeMap = std::unordered_map; - NullConstantTypeMap null_constant_type_map_; - std::unordered_set seen_null_constants_; - - Instruction* GetNullConstantForVariable(Instruction* variable_inst); - void AddNullInitializerToVariable(Instruction* constant_inst, - Instruction* variable_inst); -}; - -} // namespace opt -} // namespace spvtools - -#endif // SOURCE_OPT_GENERATE_WEBGPU_INITIALIZERS_PASS_H_ diff --git a/3rdparty/spirv-tools/source/opt/ir_loader.cpp b/3rdparty/spirv-tools/source/opt/ir_loader.cpp index 70e5144aa..e443ebb5f 100644 --- a/3rdparty/spirv-tools/source/opt/ir_loader.cpp +++ b/3rdparty/spirv-tools/source/opt/ir_loader.cpp @@ -41,6 +41,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { ++inst_index_; const auto opcode = static_cast(inst->opcode); if (IsDebugLineInst(opcode)) { + module()->SetContainsDebugInfo(); last_line_inst_.reset(); dbg_line_info_.push_back( Instruction(module()->context(), *inst, last_dbg_scope_)); @@ -61,12 +62,12 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { inlined_at = inst->words[kInlinedAtIndex]; last_dbg_scope_ = DebugScope(inst->words[kLexicalScopeIndex], inlined_at); - module()->SetContainsDebugScope(); + module()->SetContainsDebugInfo(); return true; } if (ext_inst_key == OpenCLDebugInfo100DebugNoScope) { last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); - module()->SetContainsDebugScope(); + module()->SetContainsDebugInfo(); return true; } } else { @@ -78,12 +79,12 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { inlined_at = inst->words[kInlinedAtIndex]; last_dbg_scope_ = DebugScope(inst->words[kLexicalScopeIndex], inlined_at); - module()->SetContainsDebugScope(); + module()->SetContainsDebugInfo(); return true; } if (ext_inst_key == DebugInfoDebugNoScope) { last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); - module()->SetContainsDebugScope(); + module()->SetContainsDebugInfo(); return true; } } diff --git a/3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.cpp b/3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.cpp deleted file mode 100644 index b5d5d5993..000000000 --- a/3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "source/opt/legalize_vector_shuffle_pass.h" - -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { - -Pass::Status LegalizeVectorShufflePass::Process() { - bool changed = false; - context()->module()->ForEachInst([&changed](Instruction* inst) { - if (inst->opcode() != SpvOpVectorShuffle) return; - - for (uint32_t idx = 2; idx < inst->NumInOperands(); ++idx) { - auto literal = inst->GetSingleWordInOperand(idx); - if (literal != 0xFFFFFFFF) continue; - changed = true; - inst->SetInOperand(idx, {0}); - } - }); - - return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange; -} - -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.h b/3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.h deleted file mode 100644 index ca6e1dfbe..000000000 --- a/3rdparty/spirv-tools/source/opt/legalize_vector_shuffle_pass.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SOURCE_OPT_LEGALIZE_VECTOR_SHUFFLE_PASS_H_ -#define SOURCE_OPT_LEGALIZE_VECTOR_SHUFFLE_PASS_H_ - -#include "source/opt/ir_context.h" -#include "source/opt/module.h" -#include "source/opt/pass.h" - -namespace spvtools { -namespace opt { - -// Converts any usages of 0xFFFFFFFF for the literals in OpVectorShuffle to a -// literal 0. This is needed because using OxFFFFFFFF is forbidden by the WebGPU -// spec. 0xFFFFFFFF in the main spec indicates that the result for this -// component has no source, thus is undefined. Since this is undefined -// behaviour we are free to use 0. -class LegalizeVectorShufflePass : public Pass { - public: - const char* name() const override { return "legalize-vector-shuffle"; } - Status Process() override; - - IRContext::Analysis GetPreservedAnalyses() override { - return IRContext::kAnalysisInstrToBlockMapping | - IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | - IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | - IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap | - IRContext::kAnalysisScalarEvolution | - IRContext::kAnalysisRegisterPressure | - IRContext::kAnalysisValueNumberTable | - IRContext::kAnalysisStructuredCFG | - IRContext::kAnalysisBuiltinVarId | - IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes | - IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants; - } -}; - -} // namespace opt -} // namespace spvtools - -#endif // SOURCE_OPT_LEGALIZE_VECTOR_SHUFFLE_PASS_H_ diff --git a/3rdparty/spirv-tools/source/opt/module.h b/3rdparty/spirv-tools/source/opt/module.h index 2c96f0295..d609b603a 100644 --- a/3rdparty/spirv-tools/source/opt/module.h +++ b/3rdparty/spirv-tools/source/opt/module.h @@ -49,7 +49,7 @@ class Module { using const_inst_iterator = InstructionList::const_iterator; // Creates an empty module with zero'd header. - Module() : header_({}), contains_debug_scope_(false) {} + Module() : header_({}), contains_debug_info_(false) {} // Sets the header to the given |header|. void SetHeader(const ModuleHeader& header) { header_ = header; } @@ -119,9 +119,9 @@ class Module { // Appends a function to this module. inline void AddFunction(std::unique_ptr f); - // Sets |contains_debug_scope_| as true. - inline void SetContainsDebugScope(); - inline bool ContainsDebugScope() { return contains_debug_scope_; } + // Sets |contains_debug_info_| as true. + inline void SetContainsDebugInfo(); + inline bool ContainsDebugInfo() { return contains_debug_info_; } // Returns a vector of pointers to type-declaration instructions in this // module. @@ -301,8 +301,8 @@ class Module { // any instruction. We record them here, so they will not be lost. std::vector trailing_dbg_line_info_; - // This module contains DebugScope or DebugNoScope. - bool contains_debug_scope_; + // This module contains DebugScope/DebugNoScope or OpLine/OpNoLine. + bool contains_debug_info_; }; // Pretty-prints |module| to |str|. Returns |str|. @@ -364,7 +364,7 @@ inline void Module::AddFunction(std::unique_ptr f) { functions_.emplace_back(std::move(f)); } -inline void Module::SetContainsDebugScope() { contains_debug_scope_ = true; } +inline void Module::SetContainsDebugInfo() { contains_debug_info_ = true; } inline Module::inst_iterator Module::capability_begin() { return capabilities_.begin(); diff --git a/3rdparty/spirv-tools/source/opt/optimizer.cpp b/3rdparty/spirv-tools/source/opt/optimizer.cpp index 8726ff93d..909442cc1 100644 --- a/3rdparty/spirv-tools/source/opt/optimizer.cpp +++ b/3rdparty/spirv-tools/source/opt/optimizer.cpp @@ -62,7 +62,9 @@ struct Optimizer::Impl { opt::PassManager pass_manager; // Internal implementation pass manager. }; -Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {} +Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) { + assert(env != SPV_ENV_WEBGPU_0); +} Optimizer::~Optimizer() {} @@ -239,23 +241,6 @@ Optimizer& Optimizer::RegisterSizePasses() { .RegisterPass(CreateCFGCleanupPass()); } -Optimizer& Optimizer::RegisterVulkanToWebGPUPasses() { - return RegisterPass(CreateStripAtomicCounterMemoryPass()) - .RegisterPass(CreateGenerateWebGPUInitializersPass()) - .RegisterPass(CreateLegalizeVectorShufflePass()) - .RegisterPass(CreateSplitInvalidUnreachablePass()) - .RegisterPass(CreateEliminateDeadConstantPass()) - .RegisterPass(CreateFlattenDecorationPass()) - .RegisterPass(CreateAggressiveDCEPass()) - .RegisterPass(CreateDeadBranchElimPass()) - .RegisterPass(CreateCompactIdsPass()); -} - -Optimizer& Optimizer::RegisterWebGPUToVulkanPasses() { - return RegisterPass(CreateDecomposeInitializedVariablesPass()) - .RegisterPass(CreateCompactIdsPass()); -} - bool Optimizer::RegisterPassesFromFlags(const std::vector& flags) { for (const auto& flag : flags) { if (!RegisterPassFromFlag(flag)) { @@ -298,9 +283,7 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) { // // Both Pass::name() and Pass::desc() should be static class members so they // can be invoked without creating a pass instance. - if (pass_name == "strip-atomic-counter-memory") { - RegisterPass(CreateStripAtomicCounterMemoryPass()); - } else if (pass_name == "strip-debug") { + if (pass_name == "strip-debug") { RegisterPass(CreateStripDebugInfoPass()); } else if (pass_name == "strip-reflect") { RegisterPass(CreateStripReflectInfoPass()); @@ -505,14 +488,6 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) { RegisterSizePasses(); } else if (pass_name == "legalize-hlsl") { RegisterLegalizationPasses(); - } else if (pass_name == "generate-webgpu-initializers") { - RegisterPass(CreateGenerateWebGPUInitializersPass()); - } else if (pass_name == "legalize-vector-shuffle") { - RegisterPass(CreateLegalizeVectorShufflePass()); - } else if (pass_name == "split-invalid-unreachable") { - RegisterPass(CreateSplitInvalidUnreachablePass()); - } else if (pass_name == "decompose-initialized-variables") { - RegisterPass(CreateDecomposeInitializedVariablesPass()); } else if (pass_name == "graphics-robust-access") { RegisterPass(CreateGraphicsRobustAccessPass()); } else if (pass_name == "wrap-opkill") { @@ -583,10 +558,12 @@ bool Optimizer::Run(const uint32_t* original_binary, #ifndef NDEBUG // We do not keep the result id of DebugScope in struct DebugScope. // Instead, we assign random ids for them, which results in integrity + // check failures. In addition, propagating the OpLine/OpNoLine to preserve + // the debug information through transformations results in integrity // check failures. We want to skip the integrity check when the module - // contains DebugScope instructions. + // contains DebugScope or OpLine/OpNoLine instructions. if (status == opt::Pass::Status::SuccessWithoutChange && - !context->module()->ContainsDebugScope()) { + !context->module()->ContainsDebugInfo()) { std::vector optimized_binary_with_nop; context->module()->ToBinary(&optimized_binary_with_nop, /* skip_nop = */ false); @@ -627,11 +604,6 @@ Optimizer::PassToken CreateNullPass() { return MakeUnique(MakeUnique()); } -Optimizer::PassToken CreateStripAtomicCounterMemoryPass() { - return MakeUnique( - MakeUnique()); -} - Optimizer::PassToken CreateStripDebugInfoPass() { return MakeUnique( MakeUnique()); @@ -929,31 +901,11 @@ Optimizer::PassToken CreateCodeSinkingPass() { MakeUnique()); } -Optimizer::PassToken CreateGenerateWebGPUInitializersPass() { - return MakeUnique( - MakeUnique()); -} - Optimizer::PassToken CreateFixStorageClassPass() { return MakeUnique( MakeUnique()); } -Optimizer::PassToken CreateLegalizeVectorShufflePass() { - return MakeUnique( - MakeUnique()); -} - -Optimizer::PassToken CreateDecomposeInitializedVariablesPass() { - return MakeUnique( - MakeUnique()); -} - -Optimizer::PassToken CreateSplitInvalidUnreachablePass() { - return MakeUnique( - MakeUnique()); -} - Optimizer::PassToken CreateGraphicsRobustAccessPass() { return MakeUnique( MakeUnique()); diff --git a/3rdparty/spirv-tools/source/opt/passes.h b/3rdparty/spirv-tools/source/opt/passes.h index d47cc1cee..1bc94c7e2 100644 --- a/3rdparty/spirv-tools/source/opt/passes.h +++ b/3rdparty/spirv-tools/source/opt/passes.h @@ -30,7 +30,6 @@ #include "source/opt/dead_branch_elim_pass.h" #include "source/opt/dead_insert_elim_pass.h" #include "source/opt/dead_variable_elimination.h" -#include "source/opt/decompose_initialized_variables_pass.h" #include "source/opt/desc_sroa.h" #include "source/opt/eliminate_dead_constant_pass.h" #include "source/opt/eliminate_dead_functions_pass.h" @@ -40,7 +39,6 @@ #include "source/opt/flatten_decoration_pass.h" #include "source/opt/fold_spec_constant_op_and_composite_pass.h" #include "source/opt/freeze_spec_constant_value_pass.h" -#include "source/opt/generate_webgpu_initializers_pass.h" #include "source/opt/graphics_robust_access_pass.h" #include "source/opt/if_conversion.h" #include "source/opt/inline_exhaustive_pass.h" @@ -48,7 +46,6 @@ #include "source/opt/inst_bindless_check_pass.h" #include "source/opt/inst_buff_addr_check_pass.h" #include "source/opt/inst_debug_printf_pass.h" -#include "source/opt/legalize_vector_shuffle_pass.h" #include "source/opt/licm_pass.h" #include "source/opt/local_access_chain_convert_pass.h" #include "source/opt/local_redundancy_elimination.h" @@ -70,10 +67,8 @@ #include "source/opt/scalar_replacement_pass.h" #include "source/opt/set_spec_constant_default_value_pass.h" #include "source/opt/simplification_pass.h" -#include "source/opt/split_invalid_unreachable_pass.h" #include "source/opt/ssa_rewrite_pass.h" #include "source/opt/strength_reduction_pass.h" -#include "source/opt/strip_atomic_counter_memory_pass.h" #include "source/opt/strip_debug_info_pass.h" #include "source/opt/strip_reflect_info_pass.h" #include "source/opt/unify_const_pass.h" diff --git a/3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.cpp b/3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.cpp deleted file mode 100644 index 31cfbc330..000000000 --- a/3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "source/opt/split_invalid_unreachable_pass.h" - -#include "source/opt/ir_builder.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { - -Pass::Status SplitInvalidUnreachablePass::Process() { - bool changed = false; - std::unordered_set entry_points; - for (auto entry_point : context()->module()->entry_points()) { - entry_points.insert(entry_point.GetSingleWordOperand(1)); - } - - for (auto func = context()->module()->begin(); - func != context()->module()->end(); ++func) { - if (entry_points.find(func->result_id()) == entry_points.end()) continue; - std::unordered_set continue_targets; - std::unordered_set merge_blocks; - std::unordered_set unreachable_blocks; - for (auto block = func->begin(); block != func->end(); ++block) { - unreachable_blocks.insert(&*block); - uint32_t continue_target = block->ContinueBlockIdIfAny(); - if (continue_target != 0) continue_targets.insert(continue_target); - uint32_t merge_block = block->MergeBlockIdIfAny(); - if (merge_block != 0) merge_blocks.insert(merge_block); - } - - cfg()->ForEachBlockInPostOrder( - func->entry().get(), [&unreachable_blocks](BasicBlock* inner_block) { - unreachable_blocks.erase(inner_block); - }); - - for (auto unreachable : unreachable_blocks) { - uint32_t block_id = unreachable->id(); - if (continue_targets.find(block_id) == continue_targets.end() || - merge_blocks.find(block_id) == merge_blocks.end()) { - continue; - } - - std::vector> usages; - context()->get_def_use_mgr()->ForEachUse( - unreachable->GetLabelInst(), - [&usages](Instruction* use, uint32_t idx) { - if ((use->opcode() == SpvOpLoopMerge && idx == 0) || - use->opcode() == SpvOpSelectionMerge) { - usages.push_back(std::make_pair(use, idx)); - } - }); - - for (auto usage : usages) { - Instruction* use; - uint32_t idx; - std::tie(use, idx) = usage; - uint32_t new_id = context()->TakeNextId(); - std::unique_ptr new_label( - new Instruction(context(), SpvOpLabel, 0, new_id, {})); - get_def_use_mgr()->AnalyzeInstDefUse(new_label.get()); - std::unique_ptr new_block( - new BasicBlock(std::move(new_label))); - auto* block_ptr = new_block.get(); - InstructionBuilder builder(context(), new_block.get(), - IRContext::kAnalysisDefUse | - IRContext::kAnalysisInstrToBlockMapping); - builder.AddUnreachable(); - cfg()->RegisterBlock(block_ptr); - (&*func)->InsertBasicBlockBefore(std::move(new_block), unreachable); - use->SetInOperand(0, {new_id}); - get_def_use_mgr()->UpdateDefUse(use); - cfg()->AddEdges(block_ptr); - changed = true; - } - } - } - - return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange; -} - -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.h b/3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.h deleted file mode 100644 index a5613448e..000000000 --- a/3rdparty/spirv-tools/source/opt/split_invalid_unreachable_pass.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SOURCE_OPT_SPLIT_INVALID_UNREACHABLE_PASS_H_ -#define SOURCE_OPT_SPLIT_INVALID_UNREACHABLE_PASS_H_ - -#include "source/opt/ir_context.h" -#include "source/opt/module.h" -#include "source/opt/pass.h" - -namespace spvtools { -namespace opt { - -// Attempts to legalize for WebGPU by splitting up invalid unreachable blocks. -// Specifically, looking for cases of unreachable merge-blocks and -// continue-targets that are used more then once, which is illegal in WebGPU. -class SplitInvalidUnreachablePass : public Pass { - public: - const char* name() const override { return "split-invalid-unreachable"; } - Status Process() override; - - IRContext::Analysis GetPreservedAnalyses() override { - return IRContext::kAnalysisInstrToBlockMapping | - IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | - IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | - IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap | - IRContext::kAnalysisScalarEvolution | - IRContext::kAnalysisRegisterPressure | - IRContext::kAnalysisValueNumberTable | - IRContext::kAnalysisStructuredCFG | - IRContext::kAnalysisBuiltinVarId | - IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes | - IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants; - } -}; - -} // namespace opt -} // namespace spvtools - -#endif // SOURCE_OPT_SPLIT_INVALID_UNREACHABLE_PASS_H_ diff --git a/3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp b/3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp deleted file mode 100644 index 47714b746..000000000 --- a/3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "source/opt/strip_atomic_counter_memory_pass.h" -#include "source/opt/ir_context.h" - -namespace spvtools { -namespace opt { - -Pass::Status StripAtomicCounterMemoryPass::Process() { - bool changed = false; - context()->module()->ForEachInst([this, &changed](Instruction* inst) { - auto indices = spvOpcodeMemorySemanticsOperandIndices(inst->opcode()); - if (indices.empty()) return; - - for (auto idx : indices) { - auto mem_sem_id = inst->GetSingleWordOperand(idx); - const auto& mem_sem_inst = - context()->get_def_use_mgr()->GetDef(mem_sem_id); - // The spec explicitly says that this id must be an OpConstant - auto mem_sem_val = mem_sem_inst->GetSingleWordOperand(2); - if (!(mem_sem_val & SpvMemorySemanticsAtomicCounterMemoryMask)) { - continue; - } - mem_sem_val &= ~SpvMemorySemanticsAtomicCounterMemoryMask; - - analysis::Integer int_type(32, false); - const analysis::Type* uint32_type = - context()->get_type_mgr()->GetRegisteredType(&int_type); - auto* new_const = context()->get_constant_mgr()->GetConstant( - uint32_type, {mem_sem_val}); - auto* new_const_inst = - context()->get_constant_mgr()->GetDefiningInstruction(new_const); - auto new_const_id = new_const_inst->result_id(); - - inst->SetOperand(idx, {new_const_id}); - context()->UpdateDefUse(inst); - changed = true; - } - }); - - return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange; -} - -} // namespace opt -} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h b/3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h deleted file mode 100644 index 62e274a19..000000000 --- a/3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_ -#define SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_ - -#include "source/opt/ir_context.h" -#include "source/opt/module.h" -#include "source/opt/pass.h" - -namespace spvtools { -namespace opt { - -// Removes the AtomicCounterMemory bit from the value being passed into memory -// semantics. This bit being set is ignored in Vulkan environments and -// forbidden WebGPU ones. -class StripAtomicCounterMemoryPass : public Pass { - public: - const char* name() const override { return "strip-atomic-counter-memory"; } - Status Process() override; - - IRContext::Analysis GetPreservedAnalyses() override { - return IRContext::kAnalysisInstrToBlockMapping | - IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators | - IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis | - IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap | - IRContext::kAnalysisScalarEvolution | - IRContext::kAnalysisRegisterPressure | - IRContext::kAnalysisValueNumberTable | - IRContext::kAnalysisStructuredCFG | - IRContext::kAnalysisBuiltinVarId | - IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes | - IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants; - } -}; - -} // namespace opt -} // namespace spvtools - -#endif // SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_ diff --git a/3rdparty/spirv-tools/source/spirv_target_env.cpp b/3rdparty/spirv-tools/source/spirv_target_env.cpp index e2ff99cb0..f20ebb4fb 100644 --- a/3rdparty/spirv-tools/source/spirv_target_env.cpp +++ b/3rdparty/spirv-tools/source/spirv_target_env.cpp @@ -14,6 +14,7 @@ #include "source/spirv_target_env.h" +#include #include #include @@ -61,7 +62,8 @@ const char* spvTargetEnvDescription(spv_target_env env) { case SPV_ENV_VULKAN_1_1: return "SPIR-V 1.3 (under Vulkan 1.1 semantics)"; case SPV_ENV_WEBGPU_0: - return "SPIR-V 1.3 (under WIP WebGPU semantics)"; + assert(false); + break; case SPV_ENV_UNIVERSAL_1_4: return "SPIR-V 1.4"; case SPV_ENV_VULKAN_1_1_SPIRV_1_4: @@ -98,8 +100,10 @@ uint32_t spvVersionForTargetEnv(spv_target_env env) { return SPV_SPIRV_VERSION_WORD(1, 2); case SPV_ENV_UNIVERSAL_1_3: case SPV_ENV_VULKAN_1_1: - case SPV_ENV_WEBGPU_0: return SPV_SPIRV_VERSION_WORD(1, 3); + case SPV_ENV_WEBGPU_0: + assert(false); + break; case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: return SPV_SPIRV_VERSION_WORD(1, 4); @@ -134,7 +138,6 @@ static const std::pair spvTargetEnvNameMap[] = { {"opengl4.2", SPV_ENV_OPENGL_4_2}, {"opengl4.3", SPV_ENV_OPENGL_4_3}, {"opengl4.5", SPV_ENV_OPENGL_4_5}, - {"webgpu0", SPV_ENV_WEBGPU_0}, }; bool spvParseTargetEnv(const char* s, spv_target_env* env) { @@ -200,7 +203,6 @@ bool spvIsVulkanEnv(spv_target_env env) { case SPV_ENV_OPENCL_2_2: case SPV_ENV_OPENCL_EMBEDDED_2_2: case SPV_ENV_UNIVERSAL_1_3: - case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_UNIVERSAL_1_5: return false; @@ -209,6 +211,9 @@ bool spvIsVulkanEnv(spv_target_env env) { case SPV_ENV_VULKAN_1_1_SPIRV_1_4: case SPV_ENV_VULKAN_1_2: return true; + case SPV_ENV_WEBGPU_0: + assert(false); + break; } return false; } @@ -226,7 +231,6 @@ bool spvIsOpenCLEnv(spv_target_env env) { case SPV_ENV_UNIVERSAL_1_2: case SPV_ENV_UNIVERSAL_1_3: case SPV_ENV_VULKAN_1_1: - case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: case SPV_ENV_UNIVERSAL_1_5: @@ -241,38 +245,9 @@ bool spvIsOpenCLEnv(spv_target_env env) { case SPV_ENV_OPENCL_2_1: case SPV_ENV_OPENCL_2_2: return true; - } - return false; -} - -bool spvIsWebGPUEnv(spv_target_env env) { - switch (env) { - case SPV_ENV_UNIVERSAL_1_0: - case SPV_ENV_VULKAN_1_0: - case SPV_ENV_UNIVERSAL_1_1: - case SPV_ENV_OPENGL_4_0: - case SPV_ENV_OPENGL_4_1: - case SPV_ENV_OPENGL_4_2: - case SPV_ENV_OPENGL_4_3: - case SPV_ENV_OPENGL_4_5: - case SPV_ENV_UNIVERSAL_1_2: - case SPV_ENV_UNIVERSAL_1_3: - case SPV_ENV_VULKAN_1_1: - case SPV_ENV_OPENCL_1_2: - case SPV_ENV_OPENCL_EMBEDDED_1_2: - case SPV_ENV_OPENCL_2_0: - case SPV_ENV_OPENCL_EMBEDDED_2_0: - case SPV_ENV_OPENCL_EMBEDDED_2_1: - case SPV_ENV_OPENCL_EMBEDDED_2_2: - case SPV_ENV_OPENCL_2_1: - case SPV_ENV_OPENCL_2_2: - case SPV_ENV_UNIVERSAL_1_4: - case SPV_ENV_VULKAN_1_1_SPIRV_1_4: - case SPV_ENV_UNIVERSAL_1_5: - case SPV_ENV_VULKAN_1_2: - return false; case SPV_ENV_WEBGPU_0: - return true; + assert(false); + break; } return false; } @@ -293,7 +268,6 @@ bool spvIsOpenGLEnv(spv_target_env env) { case SPV_ENV_OPENCL_EMBEDDED_2_2: case SPV_ENV_OPENCL_2_1: case SPV_ENV_OPENCL_2_2: - case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: case SPV_ENV_UNIVERSAL_1_5: @@ -305,14 +279,13 @@ bool spvIsOpenGLEnv(spv_target_env env) { case SPV_ENV_OPENGL_4_3: case SPV_ENV_OPENGL_4_5: return true; + case SPV_ENV_WEBGPU_0: + assert(false); + break; } return false; } -bool spvIsVulkanOrWebGPUEnv(spv_target_env env) { - return spvIsVulkanEnv(env) || spvIsWebGPUEnv(env); -} - std::string spvLogStringForEnv(spv_target_env env) { switch (env) { case SPV_ENV_OPENCL_1_2: @@ -338,9 +311,6 @@ std::string spvLogStringForEnv(spv_target_env env) { case SPV_ENV_VULKAN_1_2: return "Vulkan"; } - case SPV_ENV_WEBGPU_0: { - return "WebGPU"; - } case SPV_ENV_UNIVERSAL_1_0: case SPV_ENV_UNIVERSAL_1_1: case SPV_ENV_UNIVERSAL_1_2: @@ -349,6 +319,9 @@ std::string spvLogStringForEnv(spv_target_env env) { case SPV_ENV_UNIVERSAL_1_5: { return "Universal"; } + case SPV_ENV_WEBGPU_0: + assert(false); + break; } return "Unknown"; } diff --git a/3rdparty/spirv-tools/source/spirv_target_env.h b/3rdparty/spirv-tools/source/spirv_target_env.h index 1bdedf917..a804d615c 100644 --- a/3rdparty/spirv-tools/source/spirv_target_env.h +++ b/3rdparty/spirv-tools/source/spirv_target_env.h @@ -25,20 +25,14 @@ bool spvIsVulkanEnv(spv_target_env env); // Returns true if |env| is an OPENCL environment, false otherwise. bool spvIsOpenCLEnv(spv_target_env env); -// Returns true if |env| is an WEBGPU environment, false otherwise. -bool spvIsWebGPUEnv(spv_target_env env); - // Returns true if |env| is an OPENGL environment, false otherwise. bool spvIsOpenGLEnv(spv_target_env env); -// Returns true if |env| is a VULKAN or WEBGPU environment, false otherwise. -bool spvIsVulkanOrWebGPUEnv(spv_target_env env); - // Returns the version number for the given SPIR-V target environment. uint32_t spvVersionForTargetEnv(spv_target_env env); // Returns a string to use in logging messages that indicates the class of -// environment, i.e. "Vulkan", "WebGPU", "OpenCL", etc. +// environment, i.e. "Vulkan", "OpenCL", etc. std::string spvLogStringForEnv(spv_target_env env); // Returns a formatted list of all SPIR-V target environment names that diff --git a/3rdparty/spirv-tools/source/table.cpp b/3rdparty/spirv-tools/source/table.cpp index 8340e8e21..d4a2d7e96 100644 --- a/3rdparty/spirv-tools/source/table.cpp +++ b/3rdparty/spirv-tools/source/table.cpp @@ -38,7 +38,6 @@ spv_context spvContextCreate(spv_target_env env) { case SPV_ENV_UNIVERSAL_1_3: case SPV_ENV_VULKAN_1_1: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: - case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_UNIVERSAL_1_5: case SPV_ENV_VULKAN_1_2: diff --git a/3rdparty/spirv-tools/source/val/validate.cpp b/3rdparty/spirv-tools/source/val/validate.cpp index d6e992b15..a2e116b13 100644 --- a/3rdparty/spirv-tools/source/val/validate.cpp +++ b/3rdparty/spirv-tools/source/val/validate.cpp @@ -111,57 +111,6 @@ spv_result_t ValidateForwardDecls(ValidationState_t& _) { << id_str.substr(0, id_str.size() - 1); } -std::vector CalculateNamesForEntryPoint(ValidationState_t& _, - const uint32_t id) { - auto id_descriptions = _.entry_point_descriptions(id); - auto id_names = std::vector(); - id_names.reserve((id_descriptions.size())); - - for (auto description : id_descriptions) id_names.push_back(description.name); - - return id_names; -} - -spv_result_t ValidateEntryPointNameUnique(ValidationState_t& _, - const uint32_t id) { - auto id_names = CalculateNamesForEntryPoint(_, id); - const auto names = - std::unordered_set(id_names.begin(), id_names.end()); - - if (id_names.size() != names.size()) { - std::sort(id_names.begin(), id_names.end()); - for (size_t i = 0; i < id_names.size() - 1; i++) { - if (id_names[i] == id_names[i + 1]) { - return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(id)) - << "Entry point name \"" << id_names[i] - << "\" is not unique, which is not allow in WebGPU env."; - } - } - } - - for (const auto other_id : _.entry_points()) { - if (other_id == id) continue; - const auto other_id_names = CalculateNamesForEntryPoint(_, other_id); - for (const auto& other_id_name : other_id_names) { - if (names.find(other_id_name) != names.end()) { - return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(id)) - << "Entry point name \"" << other_id_name - << "\" is not unique, which is not allow in WebGPU env."; - } - } - } - - return SPV_SUCCESS; -} - -spv_result_t ValidateEntryPointNamesUnique(ValidationState_t& _) { - for (const auto id : _.entry_points()) { - auto result = ValidateEntryPointNameUnique(_, id); - if (result != SPV_SUCCESS) return result; - } - return SPV_SUCCESS; -} - // Entry point validation. Based on 2.16.1 (Universal Validation Rules) of the // SPIRV spec: // * There is at least one OpEntryPoint instruction, unless the Linkage @@ -169,8 +118,7 @@ spv_result_t ValidateEntryPointNamesUnique(ValidationState_t& _) { // * No function can be targeted by both an OpEntryPoint instruction and an // OpFunctionCall instruction. // -// Additionally enforces that entry points for Vulkan and WebGPU should not have -// recursion. And that entry names should be unique for WebGPU. +// Additionally enforces that entry points for Vulkan should not have recursion. spv_result_t ValidateEntryPoints(ValidationState_t& _) { _.ComputeFunctionToEntryPointMapping(); _.ComputeRecursiveEntryPoints(); @@ -189,21 +137,15 @@ spv_result_t ValidateEntryPoints(ValidationState_t& _) { "an OpFunctionCall instruction."; } - // For Vulkan and WebGPU, the static function-call graph for an entry point + // For Vulkan, the static function-call graph for an entry point // must not contain cycles. - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (_.recursive_entry_points().find(entry_point) != _.recursive_entry_points().end()) { return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(entry_point)) << "Entry points may not have a call graph with cycles."; } } - - // For WebGPU all entry point names must be unique. - if (spvIsWebGPUEnv(_.context()->target_env)) { - const auto result = ValidateEntryPointNamesUnique(_); - if (result != SPV_SUCCESS) return result; - } } return SPV_SUCCESS; @@ -223,12 +165,6 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( << "Invalid SPIR-V magic number."; } - if (spvIsWebGPUEnv(context.target_env) && endian != SPV_ENDIANNESS_LITTLE) { - return DiagnosticStream(position, context.consumer, "", - SPV_ERROR_INVALID_BINARY) - << "WebGPU requires SPIR-V to be little endian."; - } - spv_header_t header; if (spvBinaryHeaderGet(binary.get(), endian, &header)) { return DiagnosticStream(position, context.consumer, "", @@ -321,13 +257,6 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( } const auto called_id = inst->GetOperandAs(2); - if (spvIsWebGPUEnv(context.target_env) && - !vstate->IsFunctionCallDefined(called_id)) { - return vstate->diag(SPV_ERROR_INVALID_LAYOUT, &instruction) - << "For WebGPU, functions need to be defined before being " - "called."; - } - vstate->AddFunctionCallTarget(called_id); } diff --git a/3rdparty/spirv-tools/source/val/validate_annotation.cpp b/3rdparty/spirv-tools/source/val/validate_annotation.cpp index 8acdb9846..85d2b7515 100644 --- a/3rdparty/spirv-tools/source/val/validate_annotation.cpp +++ b/3rdparty/spirv-tools/source/val/validate_annotation.cpp @@ -22,36 +22,6 @@ namespace spvtools { namespace val { namespace { -bool IsValidWebGPUDecoration(uint32_t decoration) { - switch (decoration) { - case SpvDecorationSpecId: - case SpvDecorationBlock: - case SpvDecorationRowMajor: - case SpvDecorationColMajor: - case SpvDecorationArrayStride: - case SpvDecorationMatrixStride: - case SpvDecorationBuiltIn: - case SpvDecorationNoPerspective: - case SpvDecorationFlat: - case SpvDecorationCentroid: - case SpvDecorationRestrict: - case SpvDecorationAliased: - case SpvDecorationNonWritable: - case SpvDecorationNonReadable: - case SpvDecorationUniform: - case SpvDecorationLocation: - case SpvDecorationComponent: - case SpvDecorationIndex: - case SpvDecorationBinding: - case SpvDecorationDescriptorSet: - case SpvDecorationOffset: - case SpvDecorationNoContraction: - return true; - default: - return false; - } -} - std::string LogStringForDecoration(uint32_t decoration) { switch (decoration) { case SpvDecorationRelaxedPrecision: @@ -212,13 +182,6 @@ spv_result_t ValidateDecorate(ValidationState_t& _, const Instruction* inst) { } } - if (spvIsWebGPUEnv(_.context()->target_env) && - !IsValidWebGPUDecoration(decoration)) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpDecorate decoration '" << LogStringForDecoration(decoration) - << "' is not valid for the WebGPU execution environment."; - } - if (spvIsVulkanEnv(_.context()->target_env)) { if ((decoration == SpvDecorationGLSLShared) || (decoration == SpvDecorationGLSLPacked)) { @@ -271,25 +234,11 @@ spv_result_t ValidateMemberDecorate(ValidationState_t& _, << " members. Largest valid index is " << member_count - 1 << "."; } - const auto decoration = inst->GetOperandAs(2); - if (spvIsWebGPUEnv(_.context()->target_env) && - !IsValidWebGPUDecoration(decoration)) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpMemberDecorate decoration '" << _.getIdName(decoration) - << "' is not valid for the WebGPU execution environment."; - } - return SPV_SUCCESS; } spv_result_t ValidateDecorationGroup(ValidationState_t& _, const Instruction* inst) { - if (spvIsWebGPUEnv(_.context()->target_env)) { - return _.diag(SPV_ERROR_INVALID_BINARY, inst) - << "OpDecorationGroup is not allowed in the WebGPU execution " - << "environment."; - } - const auto decoration_group_id = inst->GetOperandAs(0); const auto decoration_group = _.FindDef(decoration_group_id); for (auto pair : decoration_group->uses()) { @@ -309,12 +258,6 @@ spv_result_t ValidateDecorationGroup(ValidationState_t& _, spv_result_t ValidateGroupDecorate(ValidationState_t& _, const Instruction* inst) { - if (spvIsWebGPUEnv(_.context()->target_env)) { - return _.diag(SPV_ERROR_INVALID_BINARY, inst) - << "OpGroupDecorate is not allowed in the WebGPU execution " - << "environment."; - } - const auto decoration_group_id = inst->GetOperandAs(0); auto decoration_group = _.FindDef(decoration_group_id); if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) { @@ -337,12 +280,6 @@ spv_result_t ValidateGroupDecorate(ValidationState_t& _, spv_result_t ValidateGroupMemberDecorate(ValidationState_t& _, const Instruction* inst) { - if (spvIsWebGPUEnv(_.context()->target_env)) { - return _.diag(SPV_ERROR_INVALID_BINARY, inst) - << "OpGroupMemberDecorate is not allowed in the WebGPU execution " - << "environment."; - } - const auto decoration_group_id = inst->GetOperandAs(0); const auto decoration_group = _.FindDef(decoration_group_id); if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) { diff --git a/3rdparty/spirv-tools/source/val/validate_atomics.cpp b/3rdparty/spirv-tools/source/val/validate_atomics.cpp index 3f1f56175..dd263a79c 100644 --- a/3rdparty/spirv-tools/source/val/validate_atomics.cpp +++ b/3rdparty/spirv-tools/source/val/validate_atomics.cpp @@ -213,7 +213,19 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) { // Then Shader rules if (_.HasCapability(SpvCapabilityShader)) { - if (storage_class == SpvStorageClassFunction) { + if (spvIsVulkanEnv(_.context()->target_env)) { + if ((storage_class != SpvStorageClassUniform) && + (storage_class != SpvStorageClassStorageBuffer) && + (storage_class != SpvStorageClassWorkgroup) && + (storage_class != SpvStorageClassImage) && + (storage_class != SpvStorageClassPhysicalStorageBuffer)) { + 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."; + } + } else if (storage_class == SpvStorageClassFunction) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << spvOpcodeString(opcode) << ": Function storage class forbidden when the Shader " diff --git a/3rdparty/spirv-tools/source/val/validate_builtins.cpp b/3rdparty/spirv-tools/source/val/validate_builtins.cpp index 4f2a3b111..7fb99089c 100644 --- a/3rdparty/spirv-tools/source/val/validate_builtins.cpp +++ b/3rdparty/spirv-tools/source/val/validate_builtins.cpp @@ -113,28 +113,6 @@ SpvStorageClass GetStorageClass(const Instruction& inst) { return SpvStorageClassMax; } -bool IsBuiltInValidForWebGPU(SpvBuiltIn label) { - switch (label) { - case SpvBuiltInPosition: - case SpvBuiltInVertexIndex: - case SpvBuiltInInstanceIndex: - case SpvBuiltInFrontFacing: - case SpvBuiltInFragCoord: - case SpvBuiltInFragDepth: - case SpvBuiltInNumWorkgroups: - case SpvBuiltInWorkgroupSize: - case SpvBuiltInLocalInvocationId: - case SpvBuiltInGlobalInvocationId: - case SpvBuiltInLocalInvocationIndex: { - return true; - } - default: - break; - } - - return false; -} - typedef enum VUIDError_ { VUIDErrorExecutionModel = 0, VUIDErrorStorageClass = 1, @@ -1260,7 +1238,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference( spv_result_t BuiltInsValidator::ValidateFragCoordAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (spv_result_t error = ValidateF32Vec( decoration, inst, 4, [this, &inst](const std::string& message) -> spv_result_t { @@ -1284,7 +1262,7 @@ spv_result_t BuiltInsValidator::ValidateFragCoordAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); if (storage_class != SpvStorageClassMax && storage_class != SpvStorageClassInput) { @@ -1322,7 +1300,7 @@ spv_result_t BuiltInsValidator::ValidateFragCoordAtReference( spv_result_t BuiltInsValidator::ValidateFragDepthAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (spv_result_t error = ValidateF32( decoration, inst, [this, &inst](const std::string& message) -> spv_result_t { @@ -1345,7 +1323,7 @@ spv_result_t BuiltInsValidator::ValidateFragDepthAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); if (storage_class != SpvStorageClassMax && storage_class != SpvStorageClassOutput) { @@ -1398,7 +1376,7 @@ spv_result_t BuiltInsValidator::ValidateFragDepthAtReference( spv_result_t BuiltInsValidator::ValidateFrontFacingAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (spv_result_t error = ValidateBool( decoration, inst, [this, &inst](const std::string& message) -> spv_result_t { @@ -1421,7 +1399,7 @@ spv_result_t BuiltInsValidator::ValidateFrontFacingAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); if (storage_class != SpvStorageClassMax && storage_class != SpvStorageClassInput) { @@ -1579,7 +1557,7 @@ spv_result_t BuiltInsValidator::ValidateInvocationIdAtReference( spv_result_t BuiltInsValidator::ValidateInstanceIndexAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (spv_result_t error = ValidateI32( decoration, inst, [this, &inst](const std::string& message) -> spv_result_t { @@ -1602,7 +1580,7 @@ spv_result_t BuiltInsValidator::ValidateInstanceIndexAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); if (storage_class != SpvStorageClassMax && storage_class != SpvStorageClassInput) { @@ -1992,46 +1970,6 @@ spv_result_t BuiltInsValidator::ValidatePositionAtReference( } } - if (spvIsWebGPUEnv(_.context()->target_env)) { - const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); - if (storage_class != SpvStorageClassMax && - storage_class != SpvStorageClassOutput) { - return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) - << "WebGPU spec allows BuiltIn Position to be only used for " - "variables with Output storage class. " - << GetReferenceDesc(decoration, built_in_inst, referenced_inst, - referenced_from_inst) - << " " << GetStorageClassDesc(referenced_from_inst); - } - - for (const SpvExecutionModel execution_model : execution_models_) { - switch (execution_model) { - case SpvExecutionModelVertex: { - if (spv_result_t error = ValidateF32Vec( - decoration, built_in_inst, 4, - [this, &referenced_from_inst]( - const std::string& message) -> spv_result_t { - return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) - << "According to the WebGPU spec BuiltIn Position " - "variable needs to be a 4-component 32-bit float " - "vector. " - << message; - })) { - return error; - } - break; - } - default: { - return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) - << "WebGPU spec allows BuiltIn Position to be used only " - "with the Vertex execution model. " - << GetReferenceDesc(decoration, built_in_inst, referenced_inst, - referenced_from_inst, execution_model); - } - } - } - } - if (function_id_ == 0) { // Propagate this rule to all dependant ids in the global scope. id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( @@ -2547,7 +2485,7 @@ spv_result_t BuiltInsValidator::ValidateTessLevelAtReference( spv_result_t BuiltInsValidator::ValidateVertexIndexAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (spv_result_t error = ValidateI32( decoration, inst, [this, &inst](const std::string& message) -> spv_result_t { @@ -2580,51 +2518,14 @@ spv_result_t BuiltInsValidator::ValidateVertexIdAtDefinition( spv_result_t BuiltInsValidator::ValidateLocalInvocationIndexAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsWebGPUEnv(_.context()->target_env)) { - if (spv_result_t error = ValidateI32( - decoration, inst, - [this, &inst](const std::string& message) -> spv_result_t { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << "According to the WebGPU spec BuiltIn " - "LocalInvocationIndex variable needs to be a 32-bit " - "int." - << message; - })) { - return error; - } - } - // Seed at reference checks with this built-in. return ValidateLocalInvocationIndexAtReference(decoration, inst, inst, inst); } spv_result_t BuiltInsValidator::ValidateLocalInvocationIndexAtReference( const Decoration& decoration, const Instruction& built_in_inst, - const Instruction& referenced_inst, + const Instruction&, const Instruction& referenced_from_inst) { - if (spvIsWebGPUEnv(_.context()->target_env)) { - const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); - if (storage_class != SpvStorageClassMax && - storage_class != SpvStorageClassInput) { - return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) - << "WebGPU spec allows BuiltIn LocalInvocationIndex to be only " - "used for variables with Input storage class. " - << GetReferenceDesc(decoration, built_in_inst, referenced_inst, - referenced_from_inst) - << " " << GetStorageClassDesc(referenced_from_inst); - } - - for (const SpvExecutionModel execution_model : execution_models_) { - if (execution_model != SpvExecutionModelGLCompute) { - return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) - << "WebGPU spec allows BuiltIn VertexIndex to be used only " - "with GLCompute execution model. " - << GetReferenceDesc(decoration, built_in_inst, referenced_inst, - referenced_from_inst, execution_model); - } - } - } - if (function_id_ == 0) { // Propagate this rule to all dependant ids in the global scope. id_to_at_reference_checks_[referenced_from_inst.id()].push_back( @@ -2640,7 +2541,7 @@ spv_result_t BuiltInsValidator::ValidateVertexIndexAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); if (storage_class != SpvStorageClassMax && storage_class != SpvStorageClassInput) { @@ -2838,7 +2739,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]); if (spv_result_t error = ValidateI32Vec( decoration, inst, 3, @@ -2867,7 +2768,7 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]); const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst); if (storage_class != SpvStorageClassMax && @@ -2887,9 +2788,7 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference( bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute || execution_model == SpvExecutionModelTaskNV || execution_model == SpvExecutionModelMeshNV; - bool has_webgpu_model = execution_model == SpvExecutionModelGLCompute; - if ((spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) || - (spvIsWebGPUEnv(_.context()->target_env) && !has_webgpu_model)) { + if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) { uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel); return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) << _.VkErrorID(vuid) @@ -3086,7 +2985,7 @@ spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition( spv_result_t BuiltInsValidator::ValidateWorkgroupSizeAtDefinition( const Decoration& decoration, const Instruction& inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env) && !spvOpcodeIsConstant(inst.opcode())) { return _.diag(SPV_ERROR_INVALID_DATA, &inst) @@ -3118,7 +3017,7 @@ spv_result_t BuiltInsValidator::ValidateWorkgroupSizeAtReference( const Decoration& decoration, const Instruction& built_in_inst, const Instruction& referenced_inst, const Instruction& referenced_from_inst) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { for (const SpvExecutionModel execution_model : execution_models_) { if (execution_model != SpvExecutionModelGLCompute) { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -3768,26 +3667,17 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition( << "BuiltIns can only target variables, structs or constants"; } - if (!spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { - // Early return. All currently implemented rules are based on Vulkan or - // WebGPU spec. + if (!spvIsVulkanEnv(_.context()->target_env)) { + // Early return. All currently implemented rules are based on Vulkan spec. // // TODO: If you are adding validation rules for environments other than - // Vulkan or WebGPU (or general rules which are not environment - // independent), then you need to modify or remove this condition. Consider - // also adding early returns into BuiltIn-specific rules, so that the system - // doesn't spawn new rules which don't do anything. + // Vulkan (or general rules which are not environment independent), then + // you need to modify or remove this condition. Consider also adding early + // returns into BuiltIn-specific rules, so that the system doesn't spawn new + // rules which don't do anything. return SPV_SUCCESS; } - if (spvIsWebGPUEnv(_.context()->target_env) && - !IsBuiltInValidForWebGPU(label)) { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << "WebGPU does not allow BuiltIn " - << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, - decoration.params()[0]); - } - // If you are adding a new BuiltIn enum, please register it here. // If the newly added enum has validation rules associated with it // consider leaving a TODO and/or creating an issue. diff --git a/3rdparty/spirv-tools/source/val/validate_capability.cpp b/3rdparty/spirv-tools/source/val/validate_capability.cpp index 4b98bc19c..8efd55420 100644 --- a/3rdparty/spirv-tools/source/val/validate_capability.cpp +++ b/3rdparty/spirv-tools/source/val/validate_capability.cpp @@ -260,19 +260,6 @@ bool IsEnabledByCapabilityOpenCL_2_0(ValidationState_t& _, return false; } -bool IsSupportGuaranteedWebGPU(uint32_t capability) { - switch (capability) { - case SpvCapabilityMatrix: - case SpvCapabilityShader: - case SpvCapabilitySampled1D: - case SpvCapabilityImage1D: - case SpvCapabilityDerivativeControl: - case SpvCapabilityImageQuery: - return true; - } - return false; -} - } // namespace // Validates that capability declarations use operands allowed in the current @@ -365,14 +352,6 @@ spv_result_t CapabilityPass(ValidationState_t& _, const Instruction* inst) { << " Profile specification" << " (or requires extension or capability)"; } - } else if (env == SPV_ENV_WEBGPU_0) { - if (!IsSupportGuaranteedWebGPU(capability) && - !IsEnabledByExtension(_, capability)) { - return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst) - << "Capability " << capability_str() - << " is not allowed by WebGPU specification" - << " (or requires extension)"; - } } return SPV_SUCCESS; diff --git a/3rdparty/spirv-tools/source/val/validate_cfg.cpp b/3rdparty/spirv-tools/source/val/validate_cfg.cpp index ca2ae1aee..a5f6e6a17 100644 --- a/3rdparty/spirv-tools/source/val/validate_cfg.cpp +++ b/3rdparty/spirv-tools/source/val/validate_cfg.cpp @@ -820,120 +820,6 @@ spv_result_t StructuredControlFlowChecks( return SPV_SUCCESS; } -spv_result_t PerformWebGPUCfgChecks(ValidationState_t& _, Function* function) { - for (auto& block : function->ordered_blocks()) { - if (block->reachable()) continue; - if (block->is_type(kBlockTypeMerge)) { - // 1. Find the referencing merge and confirm that it is reachable. - BasicBlock* merge_header = function->GetMergeHeader(block); - assert(merge_header != nullptr); - if (!merge_header->reachable()) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable merge-blocks must be referenced by " - "a reachable merge instruction."; - } - - // 2. Check that the only instructions are OpLabel and OpUnreachable. - auto* label_inst = block->label(); - auto* terminator_inst = block->terminator(); - assert(label_inst != nullptr); - assert(terminator_inst != nullptr); - - if (terminator_inst->opcode() != SpvOpUnreachable) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable merge-blocks must terminate with " - "OpUnreachable."; - } - - auto label_idx = label_inst - &_.ordered_instructions()[0]; - auto terminator_idx = terminator_inst - &_.ordered_instructions()[0]; - if (label_idx + 1 != terminator_idx) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable merge-blocks must only contain an " - "OpLabel and OpUnreachable instruction."; - } - - // 3. Use label instruction to confirm there is no uses by branches. - for (auto use : label_inst->uses()) { - const auto* use_inst = use.first; - if (spvOpcodeIsBranch(use_inst->opcode())) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable merge-blocks cannot be the target " - "of a branch."; - } - } - } else if (block->is_type(kBlockTypeContinue)) { - // 1. Find referencing loop and confirm that it is reachable. - std::vector continue_headers = - function->GetContinueHeaders(block); - if (continue_headers.empty()) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable continue-target must be referenced " - "by a loop instruction."; - } - - std::vector reachable_headers(continue_headers.size()); - auto iter = - std::copy_if(continue_headers.begin(), continue_headers.end(), - reachable_headers.begin(), - [](BasicBlock* header) { return header->reachable(); }); - reachable_headers.resize(std::distance(reachable_headers.begin(), iter)); - - if (reachable_headers.empty()) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable continue-target must be referenced " - "by a reachable loop instruction."; - } - - // 2. Check that the only instructions are OpLabel and OpBranch. - auto* label_inst = block->label(); - auto* terminator_inst = block->terminator(); - assert(label_inst != nullptr); - assert(terminator_inst != nullptr); - - if (terminator_inst->opcode() != SpvOpBranch) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable continue-target must terminate with " - "OpBranch."; - } - - auto label_idx = label_inst - &_.ordered_instructions()[0]; - auto terminator_idx = terminator_inst - &_.ordered_instructions()[0]; - if (label_idx + 1 != terminator_idx) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable continue-target must only contain " - "an OpLabel and an OpBranch instruction."; - } - - // 3. Use label instruction to confirm there is no uses by branches. - for (auto use : label_inst->uses()) { - const auto* use_inst = use.first; - if (spvOpcodeIsBranch(use_inst->opcode())) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable continue-target cannot be the " - "target of a branch."; - } - } - - // 4. Confirm that continue-target has a back edge to a reachable loop - // header block. - auto branch_target = terminator_inst->GetOperandAs(0); - for (auto* continue_header : reachable_headers) { - if (branch_target != continue_header->id()) { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, unreachable continue-target must only have a " - "back edge to a single reachable loop instruction."; - } - } - } else { - return _.diag(SPV_ERROR_INVALID_CFG, _.FindDef(block->id())) - << "For WebGPU, all blocks must be reachable, unless they are " - << "degenerate cases of merge-block or continue-target."; - } - } - return SPV_SUCCESS; -} - spv_result_t PerformCfgChecks(ValidationState_t& _) { for (auto& function : _.functions()) { // Check all referenced blocks are defined within a function @@ -1014,13 +900,6 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) { << _.getIdName(idom->id()); } } - - // For WebGPU check that all unreachable blocks are degenerate cases for - // merge-block or continue-target. - if (spvIsWebGPUEnv(_.context()->target_env)) { - spv_result_t result = PerformWebGPUCfgChecks(_, &function); - if (result != SPV_SUCCESS) return result; - } } // If we have structed control flow, check that no block has a control // flow nesting depth larger than the limit. diff --git a/3rdparty/spirv-tools/source/val/validate_composites.cpp b/3rdparty/spirv-tools/source/val/validate_composites.cpp index d5b978fff..5d6c5e377 100644 --- a/3rdparty/spirv-tools/source/val/validate_composites.cpp +++ b/3rdparty/spirv-tools/source/val/validate_composites.cpp @@ -535,12 +535,10 @@ spv_result_t ValidateVectorShuffle(ValidationState_t& _, } // All Component literals must either be FFFFFFFF or in [0, N - 1]. - // For WebGPU specifically, Component literals cannot be FFFFFFFF. auto vector1ComponentCount = vector1Type->GetOperandAs(2); auto vector2ComponentCount = vector2Type->GetOperandAs(2); auto N = vector1ComponentCount + vector2ComponentCount; auto firstLiteralIndex = 4; - const auto is_webgpu_env = spvIsWebGPUEnv(_.context()->target_env); for (size_t i = firstLiteralIndex; i < inst->operands().size(); ++i) { auto literal = inst->GetOperandAs(i); if (literal != 0xFFFFFFFF && literal >= N) { @@ -548,12 +546,6 @@ spv_result_t ValidateVectorShuffle(ValidationState_t& _, << "Component index " << literal << " is out of bounds for " << "combined (Vector1 + Vector2) size of " << N << "."; } - - if (is_webgpu_env && literal == 0xFFFFFFFF) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Component literal at operand " << i - firstLiteralIndex - << " cannot be 0xFFFFFFFF in WebGPU execution environment."; - } } if (_.HasCapability(SpvCapabilityShader) && diff --git a/3rdparty/spirv-tools/source/val/validate_extensions.cpp b/3rdparty/spirv-tools/source/val/validate_extensions.cpp index 17b044601..af6ae2b7a 100644 --- a/3rdparty/spirv-tools/source/val/validate_extensions.cpp +++ b/3rdparty/spirv-tools/source/val/validate_extensions.cpp @@ -685,34 +685,9 @@ bool IsDebugVariableWithIntScalarType(ValidationState_t& _, } // anonymous namespace -spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) { - if (spvIsWebGPUEnv(_.context()->target_env)) { - std::string extension = GetExtensionString(&(inst->c_inst())); - - if (extension != ExtensionToString(kSPV_KHR_vulkan_memory_model)) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU, the only valid parameter to OpExtension is " - << "\"" << ExtensionToString(kSPV_KHR_vulkan_memory_model) - << "\"."; - } - } - - return SPV_SUCCESS; -} - spv_result_t ValidateExtInstImport(ValidationState_t& _, const Instruction* inst) { const auto name_id = 1; - if (spvIsWebGPUEnv(_.context()->target_env)) { - const std::string name(reinterpret_cast( - inst->words().data() + inst->operands()[name_id].offset)); - if (name != "GLSL.std.450") { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU, the only valid parameter to OpExtInstImport is " - "\"GLSL.std.450\"."; - } - } - if (!_.HasExtension(kSPV_KHR_non_semantic_info)) { const std::string name(reinterpret_cast( inst->words().data() + inst->operands()[name_id].offset)); @@ -3149,7 +3124,6 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) { spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) { const SpvOp opcode = inst->opcode(); - if (opcode == SpvOpExtension) return ValidateExtension(_, inst); if (opcode == SpvOpExtInstImport) return ValidateExtInstImport(_, inst); if (opcode == SpvOpExtInst) return ValidateExtInst(_, inst); diff --git a/3rdparty/spirv-tools/source/val/validate_image.cpp b/3rdparty/spirv-tools/source/val/validate_image.cpp index 9597630b2..f5ba5d1a8 100644 --- a/3rdparty/spirv-tools/source/val/validate_image.cpp +++ b/3rdparty/spirv-tools/source/val/validate_image.cpp @@ -821,12 +821,11 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) { << "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)"; } - if (spvIsVulkanEnv(target_env) || spvIsWebGPUEnv(target_env)) { + if (spvIsVulkanEnv(target_env)) { if (info.sampled == 0) { return _.diag(SPV_ERROR_INVALID_DATA, inst) - << _.VkErrorID(4657) << "Sampled must be 1 or 2 in the " - << (spvIsVulkanEnv(target_env) ? "Vulkan" : "WebGPU") - << " environment."; + << _.VkErrorID(4657) + << "Sampled must be 1 or 2 in the Vulkan environment."; } } @@ -1469,9 +1468,9 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) { } const auto target_env = _.context()->target_env; - // Vulkan and WebGPU require the result to be a 4-element int or float + // Vulkan requires the result to be a 4-element int or float // vector. - if (spvIsVulkanEnv(target_env) || spvIsWebGPUEnv(target_env)) { + if (spvIsVulkanEnv(target_env)) { if (_.GetDimension(actual_result_type) != 4) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Expected " << GetActualResultTypeStr(opcode) diff --git a/3rdparty/spirv-tools/source/val/validate_memory.cpp b/3rdparty/spirv-tools/source/val/validate_memory.cpp index 34ca301bb..45a232daf 100644 --- a/3rdparty/spirv-tools/source/val/validate_memory.cpp +++ b/3rdparty/spirv-tools/source/val/validate_memory.cpp @@ -578,12 +578,12 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { } } - // WebGPU & Vulkan Appendix A: Check that if contains initializer, then + // Vulkan Appendix A: Check that if contains initializer, then // storage class is Output, Private, or Function. if (inst->operands().size() > 3 && storage_class != SpvStorageClassOutput && storage_class != SpvStorageClassPrivate && storage_class != SpvStorageClassFunction) { - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) { + if (spvIsVulkanEnv(_.context()->target_env)) { return _.diag(SPV_ERROR_INVALID_ID, inst) << _.VkErrorID(4651) << "OpVariable, '" << _.getIdName(inst->id()) @@ -597,20 +597,6 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { } } - // WebGPU: All variables with storage class Output, Private, or Function MUST - // have an initializer. - if (spvIsWebGPUEnv(_.context()->target_env) && inst->operands().size() <= 3 && - (storage_class == SpvStorageClassOutput || - storage_class == SpvStorageClassPrivate || - storage_class == SpvStorageClassFunction)) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpVariable, '" << _.getIdName(inst->id()) - << "', must have an initializer.\n" - << "From WebGPU execution environment spec:\n" - << "All variables in the following storage classes must have an " - << "initializer: Output, Private, or Function"; - } - if (storage_class == SpvStorageClassPhysicalStorageBufferEXT) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "PhysicalStorageBufferEXT must not be used with OpVariable."; @@ -703,41 +689,6 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { } } - // WebGPU specific validation rules for OpTypeRuntimeArray - if (spvIsWebGPUEnv(_.context()->target_env)) { - // OpTypeRuntimeArray should only ever be in an OpTypeStruct, - // so should never appear as a bare variable. - if (value_type && value_type->opcode() == SpvOpTypeRuntimeArray) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpVariable, '" << _.getIdName(inst->id()) - << "', is attempting to create memory for an illegal type, " - << "OpTypeRuntimeArray.\nFor WebGPU OpTypeRuntimeArray can only " - << "appear as the final member of an OpTypeStruct, thus cannot " - << "be instantiated via OpVariable"; - } - - // If an OpStruct has an OpTypeRuntimeArray somewhere within it, then it - // must have the storage class StorageBuffer and be decorated - // with Block. - if (value_type && value_type->opcode() == SpvOpTypeStruct) { - if (DoesStructContainRTA(_, value_type)) { - if (storage_class == SpvStorageClassStorageBuffer) { - if (!_.HasDecoration(value_id, SpvDecorationBlock)) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "For WebGPU, an OpTypeStruct variable containing an " - << "OpTypeRuntimeArray must be decorated with Block if it " - << "has storage class StorageBuffer."; - } - } else { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "For WebGPU, OpTypeStruct variables containing " - << "OpTypeRuntimeArray must have storage class of " - << "StorageBuffer"; - } - } - } - } - // Cooperative matrix types can only be allocated in Function or Private if ((storage_class != SpvStorageClassFunction && storage_class != SpvStorageClassPrivate) && diff --git a/3rdparty/spirv-tools/source/val/validate_memory_semantics.cpp b/3rdparty/spirv-tools/source/val/validate_memory_semantics.cpp index 6af720f50..8e47f8a35 100644 --- a/3rdparty/spirv-tools/source/val/validate_memory_semantics.cpp +++ b/3rdparty/spirv-tools/source/val/validate_memory_semantics.cpp @@ -56,55 +56,6 @@ spv_result_t ValidateMemorySemantics(ValidationState_t& _, return SPV_SUCCESS; } - if (spvIsWebGPUEnv(_.context()->target_env)) { - uint32_t valid_bits; - switch (inst->opcode()) { - case SpvOpControlBarrier: - if (!(value & SpvMemorySemanticsAcquireReleaseMask)) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU, AcquireRelease must be set for Memory " - "Semantics of OpControlBarrier."; - } - - if (!(value & SpvMemorySemanticsWorkgroupMemoryMask)) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU, WorkgroupMemory must be set for Memory " - "Semantics of OpControlBarrier."; - } - - valid_bits = SpvMemorySemanticsAcquireReleaseMask | - SpvMemorySemanticsWorkgroupMemoryMask; - if (value & ~valid_bits) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU only WorkgroupMemory and AcquireRelease may be " - "set for Memory Semantics of OpControlBarrier."; - } - break; - case SpvOpMemoryBarrier: - if (!(value & SpvMemorySemanticsImageMemoryMask)) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU, ImageMemory must be set for Memory Semantics " - "of OpMemoryBarrier."; - } - valid_bits = SpvMemorySemanticsImageMemoryMask; - if (value & ~valid_bits) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU only ImageMemory may be set for Memory " - "Semantics of OpMemoryBarrier."; - } - break; - default: - if (spvOpcodeIsAtomicOp(inst->opcode())) { - if (value != 0) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "For WebGPU Memory no bits may be set for Memory " - "Semantics of OpAtomic* instructions."; - } - } - break; - } - } - const size_t num_memory_order_set_bits = spvtools::utils::CountSetBits( value & (SpvMemorySemanticsAcquireMask | SpvMemorySemanticsReleaseMask | SpvMemorySemanticsAcquireReleaseMask | diff --git a/3rdparty/spirv-tools/source/val/validate_misc.cpp b/3rdparty/spirv-tools/source/val/validate_misc.cpp index b0bc92196..0c30f3ca7 100644 --- a/3rdparty/spirv-tools/source/val/validate_misc.cpp +++ b/3rdparty/spirv-tools/source/val/validate_misc.cpp @@ -37,10 +37,6 @@ spv_result_t ValidateUndef(ValidationState_t& _, const Instruction* inst) { << "Cannot create undefined values with 8- or 16-bit types"; } - if (spvIsWebGPUEnv(_.context()->target_env)) { - return _.diag(SPV_ERROR_INVALID_BINARY, inst) << "OpUndef is disallowed"; - } - return SPV_SUCCESS; } diff --git a/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp b/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp index 6facd1dee..c816b75c6 100644 --- a/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp +++ b/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp @@ -471,21 +471,6 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, } } - if (spvIsWebGPUEnv(_.context()->target_env)) { - if (mode != SpvExecutionModeOriginUpperLeft && - mode != SpvExecutionModeDepthReplacing && - mode != SpvExecutionModeDepthGreater && - mode != SpvExecutionModeDepthLess && - mode != SpvExecutionModeDepthUnchanged && - mode != SpvExecutionModeLocalSize && - mode != SpvExecutionModeLocalSizeHint) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "Execution mode must be one of OriginUpperLeft, " - "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, " - "LocalSize, or LocalSizeHint for WebGPU environment."; - } - } - return SPV_SUCCESS; } @@ -500,13 +485,6 @@ spv_result_t ValidateMemoryModel(ValidationState_t& _, "the VulkanKHR memory model is used."; } - if (spvIsWebGPUEnv(_.context()->target_env)) { - if (_.addressing_model() != SpvAddressingModelLogical) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "Addressing model must be Logical for WebGPU environment."; - } - } - if (spvIsOpenCLEnv(_.context()->target_env)) { if ((_.addressing_model() != SpvAddressingModelPhysical32) && (_.addressing_model() != SpvAddressingModelPhysical64)) { @@ -520,6 +498,15 @@ spv_result_t ValidateMemoryModel(ValidationState_t& _, } } + if (spvIsVulkanEnv(_.context()->target_env)) { + if ((_.addressing_model() != SpvAddressingModelLogical) && + (_.addressing_model() != SpvAddressingModelPhysicalStorageBuffer64)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << _.VkErrorID(4635) + << "Addressing model must be Logical or PhysicalStorageBuffer64 " + << "in the Vulkan environment."; + } + } return SPV_SUCCESS; } diff --git a/3rdparty/spirv-tools/source/val/validate_scopes.cpp b/3rdparty/spirv-tools/source/val/validate_scopes.cpp index 73cd6ca24..636d54c43 100644 --- a/3rdparty/spirv-tools/source/val/validate_scopes.cpp +++ b/3rdparty/spirv-tools/source/val/validate_scopes.cpp @@ -137,30 +137,6 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _, } } - // WebGPU Specific rules - if (spvIsWebGPUEnv(_.context()->target_env)) { - if (value != SpvScopeWorkgroup) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << spvOpcodeString(opcode) - << ": in WebGPU environment Execution Scope is limited to " - << "Workgroup"; - } else { - _.function(inst->function()->id()) - ->RegisterExecutionModelLimitation( - [](SpvExecutionModel model, std::string* message) { - if (model != SpvExecutionModelGLCompute) { - if (message) { - *message = - ": in WebGPU environment, Workgroup Execution Scope is " - "limited to GLCompute execution model"; - } - return false; - } - return true; - }); - } - } - // TODO(atgoo@github.com) Add checks for OpenCL and OpenGL environments. // General SPIRV rules @@ -260,62 +236,6 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, } } - // WebGPU specific rules - if (spvIsWebGPUEnv(_.context()->target_env)) { - switch (inst->opcode()) { - case SpvOpControlBarrier: - if (value != SpvScopeWorkgroup) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << spvOpcodeString(opcode) - << ": in WebGPU environment Memory Scope is limited to " - << "Workgroup for OpControlBarrier"; - } - break; - case SpvOpMemoryBarrier: - if (value != SpvScopeWorkgroup) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << spvOpcodeString(opcode) - << ": in WebGPU environment Memory Scope is limited to " - << "Workgroup for OpMemoryBarrier"; - } - break; - default: - if (spvOpcodeIsAtomicOp(inst->opcode())) { - if (value != SpvScopeQueueFamilyKHR) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << spvOpcodeString(opcode) - << ": in WebGPU environment Memory Scope is limited to " - << "QueueFamilyKHR for OpAtomic* operations"; - } - } - - if (value != SpvScopeWorkgroup && value != SpvScopeInvocation && - value != SpvScopeQueueFamilyKHR) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << spvOpcodeString(opcode) - << ": in WebGPU environment Memory Scope is limited to " - << "Workgroup, Invocation, and QueueFamilyKHR"; - } - break; - } - - if (value == SpvScopeWorkgroup) { - _.function(inst->function()->id()) - ->RegisterExecutionModelLimitation( - [](SpvExecutionModel model, std::string* message) { - if (model != SpvExecutionModelGLCompute) { - if (message) { - *message = - ": in WebGPU environment, Workgroup Memory Scope is " - "limited to GLCompute execution model"; - } - return false; - } - return true; - }); - } - } - // TODO(atgoo@github.com) Add checks for OpenCL and OpenGL environments. return SPV_SUCCESS; diff --git a/3rdparty/spirv-tools/source/val/validate_type.cpp b/3rdparty/spirv-tools/source/val/validate_type.cpp index 8352301b7..6a5ea3c15 100644 --- a/3rdparty/spirv-tools/source/val/validate_type.cpp +++ b/3rdparty/spirv-tools/source/val/validate_type.cpp @@ -40,21 +40,6 @@ int64_t ConstantLiteralAsInt64(uint32_t width, return static_cast(uint64_t(lo_word) | uint64_t(hi_word) << 32); } -// Returns, as an uint64_t, the literal value from an OpConstant or the -// default value of an OpSpecConstant, assuming it is an integral type. -// For signed integers, relies the rule that literal value is sign extended -// to fill out to word granularity. Assumes that the constant value -// has -int64_t ConstantLiteralAsUint64(uint32_t width, - const std::vector& const_words) { - const uint32_t lo_word = const_words[3]; - if (width <= 32) return lo_word; - assert(width <= 64); - assert(const_words.size() > 4); - const uint32_t hi_word = const_words[4]; // Must exist, per spec. - return (uint64_t(lo_word) | uint64_t(hi_word) << 32); -} - // Validates that type declarations are unique, unless multiple declarations // of the same data type are allowed by the specification. // (see section 2.8 Types and Variables) @@ -240,7 +225,7 @@ spv_result_t ValidateTypeArray(ValidationState_t& _, const Instruction* inst) { << "' is a void type."; } - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env) && + if (spvIsVulkanEnv(_.context()->target_env) && element_type->opcode() == SpvOpTypeRuntimeArray) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpTypeArray Element Type '" << _.getIdName(element_type_id) @@ -279,18 +264,6 @@ spv_result_t ValidateTypeArray(ValidationState_t& _, const Instruction* inst) { << "OpTypeArray Length '" << _.getIdName(length_id) << "' default value must be at least 1: found " << ivalue; } - if (spvIsWebGPUEnv(_.context()->target_env)) { - // WebGPU has maximum integer width of 32 bits, and max array size - // is one more than the max signed integer representation. - const uint64_t max_permitted = (uint64_t(1) << 31); - const uint64_t uvalue = ConstantLiteralAsUint64(width, length->words()); - if (uvalue > max_permitted) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Length '" << _.getIdName(length_id) - << "' size exceeds max value " << max_permitted - << " permitted by WebGPU: got " << uvalue; - } - } } break; case SpvOpConstantNull: return _.diag(SPV_ERROR_INVALID_ID, inst) @@ -322,7 +295,7 @@ spv_result_t ValidateTypeRuntimeArray(ValidationState_t& _, << _.getIdName(element_id) << "' is a void type."; } - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env) && + if (spvIsVulkanEnv(_.context()->target_env) && element_type->opcode() == SpvOpTypeRuntimeArray) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpTypeRuntimeArray Element Type '" @@ -394,7 +367,7 @@ spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) { << "."; } - if (spvIsVulkanOrWebGPUEnv(_.context()->target_env) && + if (spvIsVulkanEnv(_.context()->target_env) && member_type->opcode() == SpvOpTypeRuntimeArray) { const bool is_last_member = member_type_index == inst->operands().size() - 1; diff --git a/3rdparty/spirv-tools/source/val/validation_state.cpp b/3rdparty/spirv-tools/source/val/validation_state.cpp index fb1069de2..367506e4a 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.cpp +++ b/3rdparty/spirv-tools/source/val/validation_state.cpp @@ -1240,23 +1240,6 @@ bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const { bool ValidationState_t::IsValidStorageClass( SpvStorageClass storage_class) const { - if (spvIsWebGPUEnv(context()->target_env)) { - switch (storage_class) { - case SpvStorageClassUniformConstant: - case SpvStorageClassUniform: - case SpvStorageClassStorageBuffer: - case SpvStorageClassInput: - case SpvStorageClassOutput: - case SpvStorageClassImage: - case SpvStorageClassWorkgroup: - case SpvStorageClassPrivate: - case SpvStorageClassFunction: - return true; - default: - return false; - } - } - if (spvIsVulkanEnv(context()->target_env)) { switch (storage_class) { case SpvStorageClassUniformConstant: @@ -1667,6 +1650,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492); case 4633: return VUID_WRAP(VUID-StandaloneSpirv-None-04633); + case 4635: + return VUID_WRAP(VUID-StandaloneSpirv-None-04635); case 4642: return VUID_WRAP(VUID-StandaloneSpirv-None-04642); case 4649: @@ -1691,6 +1676,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675); case 4685: return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685); + case 4686: + return VUID_WRAP(VUID-StandaloneSpirv-None-04686); case 4711: return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711); default: