Merge changes Icd615355,I590a161a * changes: Update SPIR-V Tools to 2f2e72bae Squashed 'third_party/SPIRV-Tools/' changes from 0174dd11f..e9dc2c8ce
diff --git a/third_party/SPIRV-Tools/.bazelrc b/third_party/SPIRV-Tools/.bazelrc new file mode 100644 index 0000000..5b3d13f --- /dev/null +++ b/third_party/SPIRV-Tools/.bazelrc
@@ -0,0 +1 @@ +build --cxxopt=-std=c++17
diff --git a/third_party/SPIRV-Tools/.bazelversion b/third_party/SPIRV-Tools/.bazelversion index 28cbf7c..0062ac9 100644 --- a/third_party/SPIRV-Tools/.bazelversion +++ b/third_party/SPIRV-Tools/.bazelversion
@@ -1 +1 @@ -5.0.0 \ No newline at end of file +5.0.0
diff --git a/third_party/SPIRV-Tools/BUILD.bazel b/third_party/SPIRV-Tools/BUILD.bazel index 255d4e7..71399b2 100644 --- a/third_party/SPIRV-Tools/BUILD.bazel +++ b/third_party/SPIRV-Tools/BUILD.bazel
@@ -104,11 +104,11 @@ genrule( name = "build_version_inc", - srcs = ["CHANGES"], outs = ["build-version.inc"], - cmd = "SOURCE_DATE_EPOCH=0 $(location :update_build_version) $(location CHANGES) $(location build-version.inc)", - cmd_bat = "set SOURCE_DATE_EPOCH=0 && $(location :update_build_version) $(location CHANGES) $(location build-version.inc)", + cmd = "SOURCE_DATE_EPOCH=0 $(location :update_build_version) $(RULEDIR) $(location build-version.inc)", + cmd_bat = "set SOURCE_DATE_EPOCH=0 && $(location :update_build_version) $(RULEDIR) $(location build-version.inc)", exec_tools = [":update_build_version"], + local = True, ) # Libraries
diff --git a/third_party/SPIRV-Tools/BUILD.gn b/third_party/SPIRV-Tools/BUILD.gn index fb662c1..81d122d 100644 --- a/third_party/SPIRV-Tools/BUILD.gn +++ b/third_party/SPIRV-Tools/BUILD.gn
@@ -265,12 +265,12 @@ action("spvtools_build_version") { script = "utils/update_build_version.py" - changes_file = "CHANGES" + repo_path = "." inc_file = "${target_gen_dir}/build-version.inc" outputs = [ inc_file ] args = [ - rebase_path(changes_file, root_build_dir), + rebase_path(repo_path, root_build_dir), rebase_path(inc_file, root_build_dir), ] }
diff --git a/third_party/SPIRV-Tools/DEPS b/third_party/SPIRV-Tools/DEPS index f1866ea..c6be512 100644 --- a/third_party/SPIRV-Tools/DEPS +++ b/third_party/SPIRV-Tools/DEPS
@@ -5,14 +5,12 @@ 'effcee_revision': 'c7b4db79f340f7a9981e8a484f6d5785e24242d1', - # Pin to the last version of googletest that supports C++11. - # Anything later requires C++14 - 'googletest_revision': 'v1.12.0', + 'googletest_revision': '2f2e72bae991138cedd0e3d06a115022736cd568', # Use protobufs before they gained the dependency on abseil 'protobuf_revision': 'v3.13.0.1', - 're2_revision': '8afcf7fcc481692197e33612446d69e8f5777c54', + 're2_revision': 'b025c6a3ae05995660e3b882eb3277f4399ced1a', 'spirv_headers_revision': 'aa331ab0ffcb3a67021caa1a0c1c9017712f2f31', }
diff --git a/third_party/SPIRV-Tools/build_defs.bzl b/third_party/SPIRV-Tools/build_defs.bzl index 3a69de5..4d6f15c 100644 --- a/third_party/SPIRV-Tools/build_defs.bzl +++ b/third_party/SPIRV-Tools/build_defs.bzl
@@ -4,13 +4,10 @@ "-DSPIRV_CHECK_CONTEXT", "-DSPIRV_COLOR_TERMINAL", ] + select({ - # On Windows, assume MSVC. - # C++14 is the default in VisualStudio 2017. "@platforms//os:windows": [], "//conditions:default": [ "-DSPIRV_LINUX", "-DSPIRV_TIMER_ENABLED", - "-std=c++11", "-fvisibility=hidden", "-fno-exceptions", "-fno-rtti",
diff --git a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h index b549efb..84a7726 100644 --- a/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h +++ b/third_party/SPIRV-Tools/include/spirv-tools/libspirv.h
@@ -441,6 +441,8 @@ typedef struct spv_fuzzer_options_t spv_fuzzer_options_t; +typedef struct spv_optimizer_t spv_optimizer_t; + // Type Definitions typedef spv_const_binary_t* spv_const_binary; @@ -900,6 +902,63 @@ const size_t num_words, spv_parsed_header_fn_t parse_header, spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic); +// The optimizer interface. + +// A pointer to a function that accepts a log message from an optimizer. +typedef void (*spv_message_consumer)( + spv_message_level_t, const char*, const spv_position_t*, const char*); + +// Creates and returns an optimizer object. This object must be passed to +// optimizer APIs below and is valid until passed to spvOptimizerDestroy. +SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env); + +// Destroys the given optimizer object. +SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer); + +// Sets an spv_message_consumer on an optimizer object. +SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer( + spv_optimizer_t* optimizer, spv_message_consumer consumer); + +// Registers passes that attempt to legalize the generated code. +SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses( + spv_optimizer_t* optimizer); + +// Registers passes that attempt to improve performance of generated code. +SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses( + spv_optimizer_t* optimizer); + +// Registers passes that attempt to improve the size of generated code. +SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses( + spv_optimizer_t* optimizer); + +// Registers a pass specified by a flag in an optimizer object. +SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag( + spv_optimizer_t* optimizer, const char* flag); + +// Registers passes specified by length number of flags in an optimizer object. +SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags( + spv_optimizer_t* optimizer, const char** flags, const size_t flag_count); + +// Optimizes the SPIR-V code of size |word_count| pointed to by |binary| and +// returns an optimized spv_binary in |optimized_binary|. +// +// Returns SPV_SUCCESS on successful optimization, whether or not the module is +// modified. Returns an SPV_ERROR_* if the module fails to validate or if +// errors occur when processing using any of the registered passes. In that +// case, no further passes are executed and the |optimized_binary| contents may +// be invalid. +// +// By default, the binary is validated before any transforms are performed, +// and optionally after each transform. Validation uses SPIR-V spec rules +// for the SPIR-V version named in the binary's header (at word offset 1). +// Additionally, if the target environment is a client API (such as +// Vulkan 1.1), then validate for that client API version, to the extent +// that it is verifiable from data in the binary itself, or from the +// validator options set on the optimizer options. +SPIRV_TOOLS_EXPORT spv_result_t spvOptimizerRun( + spv_optimizer_t* optimizer, const uint32_t* binary, const size_t word_count, + spv_binary* optimized_binary, const spv_optimizer_options options); + #ifdef __cplusplus } #endif
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat deleted file mode 100644 index 25783a9..0000000 --- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat +++ /dev/null
@@ -1,23 +0,0 @@ -:: Copyright (c) 2018 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. -:: -:: Windows Build Script. - -@echo on - -:: Find out the directory of the common build script. -set SCRIPT_DIR=%~dp0 - -:: Call with correct parameter -call %SCRIPT_DIR%\..\scripts\windows\build.bat Debug 2017
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/continuous.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/continuous.cfg deleted file mode 100644 index 25c5e11..0000000 --- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/continuous.cfg +++ /dev/null
@@ -1,22 +0,0 @@ -# Copyright (c) 2018 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. - -# Continuous build configuration. -build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat" - -action { - define_artifacts { - regex: "install.zip" - } -}
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/presubmit.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/presubmit.cfg deleted file mode 100644 index a7a553a..0000000 --- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-debug/presubmit.cfg +++ /dev/null
@@ -1,16 +0,0 @@ -# Copyright (c) 2018 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. - -# Presubmit build configuration. -build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat"
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat deleted file mode 100644 index c1945e2..0000000 --- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat +++ /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. -:: -:: Windows Build Script. - -@echo on - -set SRC=%cd%\github\SPIRV-Tools - -:: Force usage of python 3.6 -set PATH=C:\python36;%PATH% - -:: Get dependencies -cd %SRC% -git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers -git clone https://github.com/google/googletest external/googletest -cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd .. -git clone --depth=1 https://github.com/google/effcee external/effcee -git clone --depth=1 https://github.com/google/re2 external/re2 - -:: REM Install Bazel. -wget -q https://github.com/bazelbuild/bazel/releases/download/5.0.0/bazel-5.0.0-windows-x86_64.zip -unzip -q bazel-5.0.0-windows-x86_64.zip - -:: Set up MSVC -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 -set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC - -:: ######################################### -:: Start building. -:: ######################################### -echo "Build everything... %DATE% %TIME%" -bazel.exe build :all -if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% -echo "Build Completed %DATE% %TIME%" - -:: ############## -:: Run the tests -:: ############## -echo "Running Tests... %DATE% %TIME%" -bazel.exe test :all -if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% -echo "Tests Completed %DATE% %TIME%" - -exit /b 0 -
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/continuous.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/continuous.cfg deleted file mode 100644 index f2387a6..0000000 --- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/continuous.cfg +++ /dev/null
@@ -1,16 +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. - -# Continuous build configuration. -build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat"
diff --git a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/presubmit.cfg b/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/presubmit.cfg deleted file mode 100644 index 13394b4..0000000 --- a/third_party/SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/presubmit.cfg +++ /dev/null
@@ -1,16 +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. - -# Presubmit build configuration. -build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-release-bazel/build.bat"
diff --git a/third_party/SPIRV-Tools/source/CMakeLists.txt b/third_party/SPIRV-Tools/source/CMakeLists.txt index acfa0c1..b5924f5 100644 --- a/third_party/SPIRV-Tools/source/CMakeLists.txt +++ b/third_party/SPIRV-Tools/source/CMakeLists.txt
@@ -195,14 +195,11 @@ ${spirv-tools_BINARY_DIR}/build-version.inc) set(SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR ${spirv-tools_SOURCE_DIR}/utils/update_build_version.py) -set(SPIRV_TOOLS_CHANGES_FILE - ${spirv-tools_SOURCE_DIR}/CHANGES) add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC} COMMAND ${PYTHON_EXECUTABLE} ${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR} - ${SPIRV_TOOLS_CHANGES_FILE} ${SPIRV_TOOLS_BUILD_VERSION_INC} + ${spirv-tools_SOURCE_DIR} ${SPIRV_TOOLS_BUILD_VERSION_INC} DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR} - ${SPIRV_TOOLS_CHANGES_FILE} COMMENT "Update build-version.inc in the SPIRV-Tools build directory (if necessary).") # Convenience target for standalone generation of the build-version.inc file. # This is not required for any dependence chain.
diff --git a/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp b/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp index 14f2208..516c34b 100644 --- a/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp +++ b/third_party/SPIRV-Tools/source/opt/const_folding_rules.cpp
@@ -145,12 +145,17 @@ if (composite->AsNullConstant()) { // Make new composite so it can be inserted in the index with the // non-null value - const auto new_composite = const_mgr->GetNullCompositeConstant(type); - // Keep track of any indexes along the way to last index - if (i != final_index) { - chain.push_back(new_composite); + if (const auto new_composite = + const_mgr->GetNullCompositeConstant(type)) { + // Keep track of any indexes along the way to last index + if (i != final_index) { + chain.push_back(new_composite); + } + components = new_composite->AsCompositeConstant()->GetComponents(); + } else { + // Unsupported input type (such as structs) + return nullptr; } - components = new_composite->AsCompositeConstant()->GetComponents(); } else { // Keep track of any indexes along the way to last index if (i != final_index) {
diff --git a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp index ad581e1..cd712f0 100644 --- a/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp +++ b/third_party/SPIRV-Tools/source/opt/inst_bindless_check_pass.cpp
@@ -497,8 +497,8 @@ if (sum_id == 0) sum_id = curr_offset_id; else { - Instruction* sum_inst = builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, - sum_id, curr_offset_id); + Instruction* sum_inst = + builder->AddIAdd(GetUintId(), sum_id, curr_offset_id); sum_id = sum_inst->result_id(); } ++ac_in_idx; @@ -507,8 +507,7 @@ uint32_t bsize = ByteSize(curr_ty_id, matrix_stride, col_major, in_matrix); uint32_t last = bsize - 1; uint32_t last_id = builder->GetUintConstantId(last); - Instruction* sum_inst = - builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, sum_id, last_id); + Instruction* sum_inst = builder->AddIAdd(GetUintId(), sum_id, last_id); return sum_inst->result_id(); }
diff --git a/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp index 97d25f3..c18f91d 100644 --- a/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp +++ b/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.cpp
@@ -257,9 +257,7 @@ uint32_t hdr_blk_id = TakeNextId(); // Branch to search loop header std::unique_ptr<Instruction> hdr_blk_label(NewLabel(hdr_blk_id)); - (void)builder.AddInstruction(MakeUnique<Instruction>( - context(), spv::Op::OpBranch, 0, 0, - std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {hdr_blk_id}}})); + (void)builder.AddBranch(hdr_blk_id); input_func->AddBasicBlock(std::move(first_blk_ptr)); // Linear search loop header block // TODO(greg-lunarg): Implement binary search @@ -293,17 +291,10 @@ uint32_t bound_test_blk_id = TakeNextId(); std::unique_ptr<Instruction> bound_test_blk_label( NewLabel(bound_test_blk_id)); - (void)builder.AddInstruction(MakeUnique<Instruction>( - context(), spv::Op::OpLoopMerge, 0, 0, - std::initializer_list<Operand>{ - {SPV_OPERAND_TYPE_ID, {bound_test_blk_id}}, - {SPV_OPERAND_TYPE_ID, {cont_blk_id}}, - {SPV_OPERAND_TYPE_LITERAL_INTEGER, - {uint32_t(spv::LoopControlMask::MaskNone)}}})); + (void)builder.AddLoopMerge(bound_test_blk_id, cont_blk_id, + uint32_t(spv::LoopControlMask::MaskNone)); // Branch to continue/work block - (void)builder.AddInstruction(MakeUnique<Instruction>( - context(), spv::Op::OpBranch, 0, 0, - std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_blk_id}}})); + (void)builder.AddBranch(cont_blk_id); input_func->AddBasicBlock(std::move(hdr_blk_ptr)); // Continue/Work Block. Read next buffer pointer and break if greater // than ref_ptr arg. @@ -386,10 +377,8 @@ GetBoolId(), spv::Op::OpULessThanEqual, ref_end_inst->result_id(), len_load_inst->result_id()); // Return test result - (void)builder.AddInstruction(MakeUnique<Instruction>( - context(), spv::Op::OpReturnValue, 0, 0, - std::initializer_list<Operand>{ - {SPV_OPERAND_TYPE_ID, {len_test_inst->result_id()}}})); + (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, + len_test_inst->result_id()); // Close block input_func->AddBasicBlock(std::move(bound_test_blk_ptr)); // Close function and add function to module @@ -422,10 +411,8 @@ uint32_t ref_len = GetTypeLength(ref_ptr_ty_inst->GetSingleWordInOperand(1)); uint32_t ref_len_id = builder->GetUintConstantId(ref_len); // Gen call to search and test function - const std::vector<uint32_t> args = {GetSearchAndTestFuncId(), *ref_uptr_id, - ref_len_id}; - Instruction* call_inst = - builder->AddNaryOp(GetBoolId(), spv::Op::OpFunctionCall, args); + Instruction* call_inst = builder->AddFunctionCall( + GetBoolId(), GetSearchAndTestFuncId(), {*ref_uptr_id, ref_len_id}); uint32_t retval = call_inst->result_id(); return retval; }
diff --git a/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp b/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp index 151b94c..4f97277 100644 --- a/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp +++ b/third_party/SPIRV-Tools/source/opt/inst_debug_printf_pass.cpp
@@ -34,8 +34,8 @@ const analysis::Type* c_ty = v_ty->element_type(); uint32_t c_ty_id = type_mgr->GetId(c_ty); for (uint32_t c = 0; c < v_ty->element_count(); ++c) { - Instruction* c_inst = builder->AddIdLiteralOp( - c_ty_id, spv::Op::OpCompositeExtract, val_inst->result_id(), c); + Instruction* c_inst = + builder->AddCompositeExtract(c_ty_id, val_inst->result_id(), {c}); GenOutputValues(c_inst, val_ids, builder); } return; @@ -44,9 +44,8 @@ // Select between uint32 zero or one uint32_t zero_id = builder->GetUintConstantId(0); uint32_t one_id = builder->GetUintConstantId(1); - Instruction* sel_inst = - builder->AddTernaryOp(GetUintId(), spv::Op::OpSelect, - val_inst->result_id(), one_id, zero_id); + Instruction* sel_inst = builder->AddSelect( + GetUintId(), val_inst->result_id(), one_id, zero_id); val_ids->push_back(sel_inst->result_id()); return; }
diff --git a/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp b/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp index 441d943..c6e4050 100644 --- a/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp +++ b/third_party/SPIRV-Tools/source/opt/instrument_pass.cpp
@@ -54,7 +54,6 @@ void InstrumentPass::MovePostludeCode( UptrVectorIterator<BasicBlock> ref_block_itr, BasicBlock* new_blk_ptr) { - // new_blk_ptr->reset(new BasicBlock(NewLabel(ref_block_itr->id()))); // Move contents of original ref block. for (auto cii = ref_block_itr->begin(); cii != ref_block_itr->end(); cii = ref_block_itr->begin()) { @@ -77,21 +76,62 @@ } std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) { - std::unique_ptr<Instruction> newLabel( - new Instruction(context(), spv::Op::OpLabel, 0, label_id, {})); - get_def_use_mgr()->AnalyzeInstDefUse(&*newLabel); - return newLabel; + auto new_label = + MakeUnique<Instruction>(context(), spv::Op::OpLabel, 0, label_id, + std::initializer_list<Operand>{}); + get_def_use_mgr()->AnalyzeInstDefUse(&*new_label); + return new_label; +} + +std::unique_ptr<Function> InstrumentPass::StartFunction( + uint32_t func_id, const analysis::Type* return_type, + const std::vector<const analysis::Type*>& param_types) { + analysis::TypeManager* type_mgr = context()->get_type_mgr(); + analysis::Function* func_type = GetFunction(return_type, param_types); + + const std::vector<Operand> operands{ + {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, + {uint32_t(spv::FunctionControlMask::MaskNone)}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_mgr->GetId(func_type)}}, + }; + auto func_inst = + MakeUnique<Instruction>(context(), spv::Op::OpFunction, + type_mgr->GetId(return_type), func_id, operands); + get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst); + return MakeUnique<Function>(std::move(func_inst)); +} + +std::unique_ptr<Instruction> InstrumentPass::EndFunction() { + auto end = MakeUnique<Instruction>(context(), spv::Op::OpFunctionEnd, 0, 0, + std::initializer_list<Operand>{}); + get_def_use_mgr()->AnalyzeInstDefUse(end.get()); + return end; +} + +std::vector<uint32_t> InstrumentPass::AddParameters( + Function& func, const std::vector<const analysis::Type*>& param_types) { + std::vector<uint32_t> param_ids; + param_ids.reserve(param_types.size()); + for (const analysis::Type* param : param_types) { + uint32_t pid = TakeNextId(); + param_ids.push_back(pid); + auto param_inst = + MakeUnique<Instruction>(context(), spv::Op::OpFunctionParameter, + context()->get_type_mgr()->GetId(param), pid, + std::initializer_list<Operand>{}); + get_def_use_mgr()->AnalyzeInstDefUse(param_inst.get()); + func.AddParameter(std::move(param_inst)); + } + return param_ids; } std::unique_ptr<Instruction> InstrumentPass::NewName( uint32_t id, const std::string& name_str) { - std::unique_ptr<Instruction> new_name(new Instruction( + return MakeUnique<Instruction>( context(), spv::Op::OpName, 0, 0, std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {id}}, - {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}})); - - return new_name; + {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}); } std::unique_ptr<Instruction> InstrumentPass::NewGlobalName( @@ -118,14 +158,12 @@ std::unique_ptr<Instruction> InstrumentPass::NewMemberName( uint32_t id, uint32_t member_index, const std::string& name_str) { - std::unique_ptr<Instruction> new_name(new Instruction( + return MakeUnique<Instruction>( context(), spv::Op::OpMemberName, 0, 0, std::initializer_list<Operand>{ {SPV_OPERAND_TYPE_ID, {id}}, {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index}}, - {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}})); - - return new_name; + {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}); } uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id, @@ -167,17 +205,15 @@ // Cast value to 32-bit unsigned if necessary uint32_t val_id = GenUintCastCode(field_value_id, builder); // Store value - Instruction* data_idx_inst = - builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, base_offset_id, - builder->GetUintConstantId(field_offset)); + Instruction* data_idx_inst = builder->AddIAdd( + GetUintId(), base_offset_id, builder->GetUintConstantId(field_offset)); uint32_t buf_id = GetOutputBufferId(); uint32_t buf_uint_ptr_id = GetOutputBufferPtrId(); - Instruction* achain_inst = - builder->AddTernaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id, - builder->GetUintConstantId(kDebugOutputDataOffset), - data_idx_inst->result_id()); - (void)builder->AddBinaryOp(0, spv::Op::OpStore, achain_inst->result_id(), - val_id); + Instruction* achain_inst = builder->AddAccessChain( + buf_uint_ptr_id, buf_id, + {builder->GetUintConstantId(kDebugOutputDataOffset), + data_idx_inst->result_id()}); + (void)builder->AddStore(achain_inst->result_id(), val_id); } void InstrumentPass::GenCommonStreamWriteCode(uint32_t record_sz, @@ -202,8 +238,8 @@ void InstrumentPass::GenFragCoordEltDebugOutputCode( uint32_t base_offset_id, uint32_t uint_frag_coord_id, uint32_t element, InstructionBuilder* builder) { - Instruction* element_val_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, uint_frag_coord_id, element); + Instruction* element_val_inst = + builder->AddCompositeExtract(GetUintId(), uint_frag_coord_id, {element}); GenDebugOutputFieldCode(base_offset_id, kInstFragOutFragCoordX + element, element_val_inst->result_id(), builder); } @@ -212,8 +248,7 @@ InstructionBuilder* builder) { Instruction* var_inst = get_def_use_mgr()->GetDef(var_id); uint32_t type_id = GetPointeeTypeId(var_inst); - Instruction* load_inst = - builder->AddUnaryOp(type_id, spv::Op::OpLoad, var_id); + Instruction* load_inst = builder->AddLoad(type_id, var_id); return load_inst->result_id(); } @@ -249,12 +284,12 @@ uint32_t load_id = GenVarLoad(context()->GetBuiltinInputVarId(uint32_t( spv::BuiltIn::GlobalInvocationId)), builder); - Instruction* x_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, load_id, 0); - Instruction* y_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, load_id, 1); - Instruction* z_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, load_id, 2); + Instruction* x_inst = + builder->AddCompositeExtract(GetUintId(), load_id, {0}); + Instruction* y_inst = + builder->AddCompositeExtract(GetUintId(), load_id, {1}); + Instruction* z_inst = + builder->AddCompositeExtract(GetUintId(), load_id, {2}); GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX, x_inst->result_id(), builder); GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY, @@ -291,10 +326,10 @@ Instruction* uvec3_cast_inst = builder->AddUnaryOp(GetVec3UintId(), spv::Op::OpBitcast, load_id); uint32_t uvec3_cast_id = uvec3_cast_inst->result_id(); - Instruction* u_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 0); - Instruction* v_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 1); + Instruction* u_inst = + builder->AddCompositeExtract(GetUintId(), uvec3_cast_id, {0}); + Instruction* v_inst = + builder->AddCompositeExtract(GetUintId(), uvec3_cast_id, {1}); GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU, u_inst->result_id(), builder); GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV, @@ -302,8 +337,8 @@ } break; case spv::ExecutionModel::Fragment: { // Load FragCoord and convert to Uint - Instruction* frag_coord_inst = builder->AddUnaryOp( - GetVec4FloatId(), spv::Op::OpLoad, + Instruction* frag_coord_inst = builder->AddLoad( + GetVec4FloatId(), context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::FragCoord))); Instruction* uint_frag_coord_inst = builder->AddUnaryOp( GetVec4UintId(), spv::Op::OpBitcast, frag_coord_inst->result_id()); @@ -321,12 +356,12 @@ uint32_t launch_id = GenVarLoad( context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::LaunchIdNV)), builder); - Instruction* x_launch_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, launch_id, 0); - Instruction* y_launch_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, launch_id, 1); - Instruction* z_launch_inst = builder->AddIdLiteralOp( - GetUintId(), spv::Op::OpCompositeExtract, launch_id, 2); + Instruction* x_launch_inst = + builder->AddCompositeExtract(GetUintId(), launch_id, {0}); + Instruction* y_launch_inst = + builder->AddCompositeExtract(GetUintId(), launch_id, {1}); + Instruction* z_launch_inst = + builder->AddCompositeExtract(GetUintId(), launch_id, {2}); GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdX, x_launch_inst->result_id(), builder); GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdY, @@ -344,11 +379,10 @@ // Call debug output function. Pass func_idx, instruction_idx and // validation ids as args. uint32_t val_id_cnt = static_cast<uint32_t>(validation_ids.size()); - uint32_t output_func_id = GetStreamWriteFunctionId(stage_idx, val_id_cnt); - std::vector<uint32_t> args = {output_func_id, - builder->GetUintConstantId(instruction_idx)}; + std::vector<uint32_t> args = {builder->GetUintConstantId(instruction_idx)}; (void)args.insert(args.end(), validation_ids.begin(), validation_ids.end()); - (void)builder->AddNaryOp(GetVoidId(), spv::Op::OpFunctionCall, args); + (void)builder->AddFunctionCall( + GetVoidId(), GetStreamWriteFunctionId(stage_idx, val_id_cnt), args); } bool InstrumentPass::AllConstant(const std::vector<uint32_t>& ids) { @@ -360,33 +394,38 @@ } uint32_t InstrumentPass::GenDebugDirectRead( - const std::vector<uint32_t>& offset_ids, InstructionBuilder* ref_builder) { + const std::vector<uint32_t>& offset_ids, InstructionBuilder* builder) { // Call debug input function. Pass func_idx and offset ids as args. - uint32_t off_id_cnt = static_cast<uint32_t>(offset_ids.size()); - uint32_t input_func_id = GetDirectReadFunctionId(off_id_cnt); - std::vector<uint32_t> args = {input_func_id}; - (void)args.insert(args.end(), offset_ids.begin(), offset_ids.end()); + const uint32_t off_id_cnt = static_cast<uint32_t>(offset_ids.size()); + const uint32_t input_func_id = GetDirectReadFunctionId(off_id_cnt); + return GenReadFunctionCall(input_func_id, offset_ids, builder); +} + +uint32_t InstrumentPass::GenReadFunctionCall( + uint32_t func_id, const std::vector<uint32_t>& func_call_args, + InstructionBuilder* ref_builder) { // If optimizing direct reads and the call has already been generated, // use its result if (opt_direct_reads_) { - uint32_t res_id = call2id_[args]; + uint32_t res_id = call2id_[func_call_args]; if (res_id != 0) return res_id; } - // If the offsets are all constants, the call can be moved to the first block - // of the function where its result can be reused. One example where this is - // profitable is for uniform buffer references, of which there are often many. + // If the function arguments are all constants, the call can be moved to the + // first block of the function where its result can be reused. One example + // where this is profitable is for uniform buffer references, of which there + // are often many. InstructionBuilder builder(ref_builder->GetContext(), &*ref_builder->GetInsertPoint(), ref_builder->GetPreservedAnalysis()); - bool insert_in_first_block = opt_direct_reads_ && AllConstant(offset_ids); + bool insert_in_first_block = opt_direct_reads_ && AllConstant(func_call_args); if (insert_in_first_block) { Instruction* insert_before = &*curr_func_->begin()->tail(); builder.SetInsertPoint(insert_before); } uint32_t res_id = - builder.AddNaryOp(GetUintId(), spv::Op::OpFunctionCall, args) + builder.AddFunctionCall(GetUintId(), func_id, func_call_args) ->result_id(); - if (insert_in_first_block) call2id_[args] = res_id; + if (insert_in_first_block) call2id_[func_call_args] = res_id; return res_id; } @@ -502,32 +541,61 @@ return 0; } -analysis::Type* InstrumentPass::GetUintXRuntimeArrayType( - uint32_t width, analysis::Type** rarr_ty) { +analysis::Integer* InstrumentPass::GetInteger(uint32_t width, bool is_signed) { + analysis::Integer i(width, is_signed); + analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&i); + assert(type && type->AsInteger()); + return type->AsInteger(); +} + +analysis::Struct* InstrumentPass::GetStruct( + const std::vector<const analysis::Type*>& fields) { + analysis::Struct s(fields); + analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&s); + assert(type && type->AsStruct()); + return type->AsStruct(); +} + +analysis::RuntimeArray* InstrumentPass::GetRuntimeArray( + const analysis::Type* element) { + analysis::RuntimeArray r(element); + analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&r); + assert(type && type->AsRuntimeArray()); + return type->AsRuntimeArray(); +} + +analysis::Function* InstrumentPass::GetFunction( + const analysis::Type* return_val, + const std::vector<const analysis::Type*>& args) { + analysis::Function func(return_val, args); + analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&func); + assert(type && type->AsFunction()); + return type->AsFunction(); +} + +analysis::RuntimeArray* InstrumentPass::GetUintXRuntimeArrayType( + uint32_t width, analysis::RuntimeArray** rarr_ty) { if (*rarr_ty == nullptr) { - analysis::DecorationManager* deco_mgr = get_decoration_mgr(); - analysis::TypeManager* type_mgr = context()->get_type_mgr(); - analysis::Integer uint_ty(width, false); - analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty); - analysis::RuntimeArray uint_rarr_ty_tmp(reg_uint_ty); - *rarr_ty = type_mgr->GetRegisteredType(&uint_rarr_ty_tmp); - uint32_t uint_arr_ty_id = type_mgr->GetTypeInstruction(*rarr_ty); + *rarr_ty = GetRuntimeArray(GetInteger(width, false)); + uint32_t uint_arr_ty_id = + context()->get_type_mgr()->GetTypeInstruction(*rarr_ty); // By the Vulkan spec, a pre-existing RuntimeArray of uint must be part of // a block, and will therefore be decorated with an ArrayStride. Therefore // the undecorated type returned here will not be pre-existing and can // safely be decorated. Since this type is now decorated, it is out of // sync with the TypeManager and therefore the TypeManager must be // invalidated after this pass. - assert(context()->get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 && + assert(get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 && "used RuntimeArray type returned"); - deco_mgr->AddDecorationVal( + get_decoration_mgr()->AddDecorationVal( uint_arr_ty_id, uint32_t(spv::Decoration::ArrayStride), width / 8u); } return *rarr_ty; } -analysis::Type* InstrumentPass::GetUintRuntimeArrayType(uint32_t width) { - analysis::Type** rarr_ty = +analysis::RuntimeArray* InstrumentPass::GetUintRuntimeArrayType( + uint32_t width) { + analysis::RuntimeArray** rarr_ty = (width == 64) ? &uint64_rarr_ty_ : &uint32_rarr_ty_; return GetUintXRuntimeArrayType(width, rarr_ty); } @@ -546,11 +614,10 @@ // If not created yet, create one analysis::DecorationManager* deco_mgr = get_decoration_mgr(); analysis::TypeManager* type_mgr = context()->get_type_mgr(); - analysis::Type* reg_uint_rarr_ty = GetUintRuntimeArrayType(32); - analysis::Integer uint_ty(32, false); - analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty); - analysis::Struct buf_ty({reg_uint_ty, reg_uint_ty, reg_uint_rarr_ty}); - analysis::Type* reg_buf_ty = type_mgr->GetRegisteredType(&buf_ty); + analysis::RuntimeArray* reg_uint_rarr_ty = GetUintRuntimeArrayType(32); + analysis::Integer* reg_uint_ty = GetInteger(32, false); + analysis::Type* reg_buf_ty = + GetStruct({reg_uint_ty, reg_uint_ty, reg_uint_rarr_ty}); uint32_t obufTyId = type_mgr->GetTypeInstruction(reg_buf_ty); // By the Vulkan spec, a pre-existing struct containing a RuntimeArray // must be a block, and will therefore be decorated with Block. Therefore @@ -604,8 +671,7 @@ analysis::TypeManager* type_mgr = context()->get_type_mgr(); uint32_t width = (validation_id_ == kInstValidationIdBuffAddr) ? 64u : 32u; analysis::Type* reg_uint_rarr_ty = GetUintRuntimeArrayType(width); - analysis::Struct buf_ty({reg_uint_rarr_ty}); - analysis::Type* reg_buf_ty = type_mgr->GetRegisteredType(&buf_ty); + analysis::Struct* reg_buf_ty = GetStruct({reg_uint_rarr_ty}); uint32_t ibufTyId = type_mgr->GetTypeInstruction(reg_buf_ty); // By the Vulkan spec, a pre-existing struct containing a RuntimeArray // must be a block, and will therefore be decorated with Block. Therefore @@ -747,37 +813,17 @@ // Create function param2output_func_id_[param_cnt] = TakeNextId(); analysis::TypeManager* type_mgr = context()->get_type_mgr(); - std::vector<const analysis::Type*> param_types; - for (uint32_t c = 0; c < param_cnt; ++c) - param_types.push_back(type_mgr->GetType(GetUintId())); - analysis::Function func_ty(type_mgr->GetType(GetVoidId()), param_types); - analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty); - std::unique_ptr<Instruction> func_inst( - new Instruction(get_module()->context(), spv::Op::OpFunction, - GetVoidId(), param2output_func_id_[param_cnt], - {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, - {uint32_t(spv::FunctionControlMask::MaskNone)}}, - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {type_mgr->GetTypeInstruction(reg_func_ty)}}})); - get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst); - std::unique_ptr<Function> output_func = - MakeUnique<Function>(std::move(func_inst)); - // Add parameters - std::vector<uint32_t> param_vec; - for (uint32_t c = 0; c < param_cnt; ++c) { - uint32_t pid = TakeNextId(); - param_vec.push_back(pid); - std::unique_ptr<Instruction> param_inst( - new Instruction(get_module()->context(), spv::Op::OpFunctionParameter, - GetUintId(), pid, {})); - get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst); - output_func->AddParameter(std::move(param_inst)); - } + + const std::vector<const analysis::Type*> param_types(param_cnt, + GetInteger(32, false)); + std::unique_ptr<Function> output_func = StartFunction( + param2output_func_id_[param_cnt], type_mgr->GetVoidType(), param_types); + + std::vector<uint32_t> param_ids = AddParameters(*output_func, param_types); + // Create first block - uint32_t test_blk_id = TakeNextId(); - std::unique_ptr<Instruction> test_label(NewLabel(test_blk_id)); - std::unique_ptr<BasicBlock> new_blk_ptr = - MakeUnique<BasicBlock>(std::move(test_label)); + auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId())); + InstructionBuilder builder( context(), &*new_blk_ptr, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); @@ -786,9 +832,9 @@ uint32_t obuf_record_sz = val_spec_offset + val_spec_param_cnt; uint32_t buf_id = GetOutputBufferId(); uint32_t buf_uint_ptr_id = GetOutputBufferPtrId(); - Instruction* obuf_curr_sz_ac_inst = - builder.AddBinaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id, - builder.GetUintConstantId(kDebugOutputSizeOffset)); + Instruction* obuf_curr_sz_ac_inst = builder.AddAccessChain( + buf_uint_ptr_id, buf_id, + {builder.GetUintConstantId(kDebugOutputSizeOffset)}); // Fetch the current debug buffer written size atomically, adding the // size of the record to be written. uint32_t obuf_record_sz_id = builder.GetUintConstantId(obuf_record_sz); @@ -802,8 +848,8 @@ uint32_t obuf_curr_sz_id = obuf_curr_sz_inst->result_id(); // Compute new written size Instruction* obuf_new_sz_inst = - builder.AddBinaryOp(GetUintId(), spv::Op::OpIAdd, obuf_curr_sz_id, - builder.GetUintConstantId(obuf_record_sz)); + builder.AddIAdd(GetUintId(), obuf_curr_sz_id, + builder.GetUintConstantId(obuf_record_sz)); // Fetch the data bound Instruction* obuf_bnd_inst = builder.AddIdLiteralOp(GetUintId(), spv::Op::OpArrayLength, @@ -825,13 +871,13 @@ new_blk_ptr = MakeUnique<BasicBlock>(std::move(write_label)); builder.SetInsertPoint(&*new_blk_ptr); // Generate common and stage-specific debug record members - GenCommonStreamWriteCode(obuf_record_sz, param_vec[kInstCommonParamInstIdx], + GenCommonStreamWriteCode(obuf_record_sz, param_ids[kInstCommonParamInstIdx], stage_idx, obuf_curr_sz_id, &builder); GenStageStreamWriteCode(stage_idx, obuf_curr_sz_id, &builder); // Gen writes of validation specific data for (uint32_t i = 0; i < val_spec_param_cnt; ++i) { GenDebugOutputFieldCode(obuf_curr_sz_id, val_spec_offset + i, - param_vec[kInstCommonParamCnt + i], &builder); + param_ids[kInstCommonParamCnt + i], &builder); } // Close write block and gen merge block (void)builder.AddBranch(merge_blk_id); @@ -840,11 +886,9 @@ builder.SetInsertPoint(&*new_blk_ptr); // Close merge block and function and add function to module (void)builder.AddNullaryOp(0, spv::Op::OpReturn); + output_func->AddBasicBlock(std::move(new_blk_ptr)); - std::unique_ptr<Instruction> func_end_inst(new Instruction( - get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {})); - get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst); - output_func->SetFunctionEnd(std::move(func_end_inst)); + output_func->SetFunctionEnd(EndFunction()); context()->AddFunction(std::move(output_func)); std::string name("stream_write_"); @@ -861,77 +905,48 @@ if (func_id != 0) return func_id; // Create input function for param_cnt. func_id = TakeNextId(); - analysis::TypeManager* type_mgr = context()->get_type_mgr(); - std::vector<const analysis::Type*> param_types; - for (uint32_t c = 0; c < param_cnt; ++c) - param_types.push_back(type_mgr->GetType(GetUintId())); - uint32_t ibuf_type_id = GetInputBufferTypeId(); - analysis::Function func_ty(type_mgr->GetType(ibuf_type_id), param_types); - analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty); - std::unique_ptr<Instruction> func_inst(new Instruction( - get_module()->context(), spv::Op::OpFunction, ibuf_type_id, func_id, - {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, - {uint32_t(spv::FunctionControlMask::MaskNone)}}, - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {type_mgr->GetTypeInstruction(reg_func_ty)}}})); - get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst); + analysis::Integer* uint_type = GetInteger(32, false); + std::vector<const analysis::Type*> param_types(param_cnt, uint_type); + std::unique_ptr<Function> input_func = - MakeUnique<Function>(std::move(func_inst)); - // Add parameters - std::vector<uint32_t> param_vec; - for (uint32_t c = 0; c < param_cnt; ++c) { - uint32_t pid = TakeNextId(); - param_vec.push_back(pid); - std::unique_ptr<Instruction> param_inst( - new Instruction(get_module()->context(), spv::Op::OpFunctionParameter, - GetUintId(), pid, {})); - get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst); - input_func->AddParameter(std::move(param_inst)); - } + StartFunction(func_id, uint_type, param_types); + std::vector<uint32_t> param_ids = AddParameters(*input_func, param_types); + // Create block - uint32_t blk_id = TakeNextId(); - std::unique_ptr<Instruction> blk_label(NewLabel(blk_id)); - std::unique_ptr<BasicBlock> new_blk_ptr = - MakeUnique<BasicBlock>(std::move(blk_label)); + auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId())); InstructionBuilder builder( context(), &*new_blk_ptr, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); // For each offset parameter, generate new offset with parameter, adding last // loaded value if it exists, and load value from input buffer at new offset. // Return last loaded value. + uint32_t ibuf_type_id = GetInputBufferTypeId(); uint32_t buf_id = GetInputBufferId(); uint32_t buf_ptr_id = GetInputBufferPtrId(); uint32_t last_value_id = 0; for (uint32_t p = 0; p < param_cnt; ++p) { uint32_t offset_id; if (p == 0) { - offset_id = param_vec[0]; + offset_id = param_ids[0]; } else { if (ibuf_type_id != GetUintId()) { - Instruction* ucvt_inst = - builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id); - last_value_id = ucvt_inst->result_id(); + last_value_id = + builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id) + ->result_id(); } - Instruction* offset_inst = builder.AddBinaryOp( - GetUintId(), spv::Op::OpIAdd, last_value_id, param_vec[p]); - offset_id = offset_inst->result_id(); + offset_id = builder.AddIAdd(GetUintId(), last_value_id, param_ids[p]) + ->result_id(); } - Instruction* ac_inst = builder.AddTernaryOp( - buf_ptr_id, spv::Op::OpAccessChain, buf_id, - builder.GetUintConstantId(kDebugInputDataOffset), offset_id); - Instruction* load_inst = - builder.AddUnaryOp(ibuf_type_id, spv::Op::OpLoad, ac_inst->result_id()); - last_value_id = load_inst->result_id(); + Instruction* ac_inst = builder.AddAccessChain( + buf_ptr_id, buf_id, + {builder.GetUintConstantId(kDebugInputDataOffset), offset_id}); + last_value_id = + builder.AddLoad(ibuf_type_id, ac_inst->result_id())->result_id(); } - (void)builder.AddInstruction(MakeUnique<Instruction>( - context(), spv::Op::OpReturnValue, 0, 0, - std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {last_value_id}}})); + (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, last_value_id); // Close block and function and add function to module input_func->AddBasicBlock(std::move(new_blk_ptr)); - std::unique_ptr<Instruction> func_end_inst(new Instruction( - get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {})); - get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst); - input_func->SetFunctionEnd(std::move(func_end_inst)); + input_func->SetFunctionEnd(EndFunction()); context()->AddFunction(std::move(input_func)); std::string name("direct_read_");
diff --git a/third_party/SPIRV-Tools/source/opt/instrument_pass.h b/third_party/SPIRV-Tools/source/opt/instrument_pass.h index e98ba88..1311929 100644 --- a/third_party/SPIRV-Tools/source/opt/instrument_pass.h +++ b/third_party/SPIRV-Tools/source/opt/instrument_pass.h
@@ -214,6 +214,10 @@ uint32_t GenDebugDirectRead(const std::vector<uint32_t>& offset_ids, InstructionBuilder* builder); + uint32_t GenReadFunctionCall(uint32_t func_id, + const std::vector<uint32_t>& args, + InstructionBuilder* builder); + // Generate code to convert integer |value_id| to 32bit, if needed. Return // an id to the 32bit equivalent. uint32_t Gen32BitCvtCode(uint32_t value_id, InstructionBuilder* builder); @@ -222,6 +226,15 @@ // Return an id to the Uint equivalent. uint32_t GenUintCastCode(uint32_t value_id, InstructionBuilder* builder); + std::unique_ptr<Function> StartFunction( + uint32_t func_id, const analysis::Type* return_type, + const std::vector<const analysis::Type*>& param_types); + + std::vector<uint32_t> AddParameters( + Function& func, const std::vector<const analysis::Type*>& param_types); + + std::unique_ptr<Instruction> EndFunction(); + // Return new label. std::unique_ptr<Instruction> NewLabel(uint32_t label_id); @@ -253,12 +266,20 @@ // Return id for void type uint32_t GetVoidId(); - // Return pointer to type for runtime array of uint - analysis::Type* GetUintXRuntimeArrayType(uint32_t width, - analysis::Type** rarr_ty); + // Get registered type structures + analysis::Integer* GetInteger(uint32_t width, bool is_signed); + analysis::Struct* GetStruct(const std::vector<const analysis::Type*>& fields); + analysis::RuntimeArray* GetRuntimeArray(const analysis::Type* element); + analysis::Function* GetFunction( + const analysis::Type* return_val, + const std::vector<const analysis::Type*>& args); // Return pointer to type for runtime array of uint - analysis::Type* GetUintRuntimeArrayType(uint32_t width); + analysis::RuntimeArray* GetUintXRuntimeArrayType( + uint32_t width, analysis::RuntimeArray** rarr_ty); + + // Return pointer to type for runtime array of uint + analysis::RuntimeArray* GetUintRuntimeArrayType(uint32_t width); // Return id for buffer uint type uint32_t GetOutputBufferPtrId(); @@ -448,10 +469,10 @@ bool storage_buffer_ext_defined_; // runtime array of uint type - analysis::Type* uint64_rarr_ty_; + analysis::RuntimeArray* uint64_rarr_ty_; // runtime array of uint type - analysis::Type* uint32_rarr_ty_; + analysis::RuntimeArray* uint32_rarr_ty_; // Pre-instrumentation same-block insts std::unordered_map<uint32_t, Instruction*> same_block_pre_;
diff --git a/third_party/SPIRV-Tools/source/opt/optimizer.cpp b/third_party/SPIRV-Tools/source/opt/optimizer.cpp index be0daeb..cbc4b82 100644 --- a/third_party/SPIRV-Tools/source/opt/optimizer.cpp +++ b/third_party/SPIRV-Tools/source/opt/optimizer.cpp
@@ -1065,3 +1065,95 @@ MakeUnique<opt::FixFuncCallArgumentsPass>()); } } // namespace spvtools + +extern "C" { + +SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env) { + return reinterpret_cast<spv_optimizer_t*>(new spvtools::Optimizer(env)); +} + +SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer) { + delete reinterpret_cast<spvtools::Optimizer*>(optimizer); +} + +SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer( + spv_optimizer_t* optimizer, spv_message_consumer consumer) { + reinterpret_cast<spvtools::Optimizer*>(optimizer)-> + SetMessageConsumer( + [consumer](spv_message_level_t level, const char* source, + const spv_position_t& position, const char* message) { + return consumer(level, source, &position, message); + }); +} + +SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses( + spv_optimizer_t* optimizer) { + reinterpret_cast<spvtools::Optimizer*>(optimizer)-> + RegisterLegalizationPasses(); +} + +SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses( + spv_optimizer_t* optimizer) { + reinterpret_cast<spvtools::Optimizer*>(optimizer)-> + RegisterPerformancePasses(); +} + +SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses( + spv_optimizer_t* optimizer) { + reinterpret_cast<spvtools::Optimizer*>(optimizer)->RegisterSizePasses(); +} + +SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag( + spv_optimizer_t* optimizer, const char* flag) +{ + return reinterpret_cast<spvtools::Optimizer*>(optimizer)-> + RegisterPassFromFlag(flag); +} + +SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags( + spv_optimizer_t* optimizer, const char** flags, const size_t flag_count) { + std::vector<std::string> opt_flags; + for (uint32_t i = 0; i < flag_count; i++) { + opt_flags.emplace_back(flags[i]); + } + + return reinterpret_cast<spvtools::Optimizer*>(optimizer)-> + RegisterPassesFromFlags(opt_flags); +} + +SPIRV_TOOLS_EXPORT +spv_result_t spvOptimizerRun(spv_optimizer_t* optimizer, + const uint32_t* binary, + const size_t word_count, + spv_binary* optimized_binary, + const spv_optimizer_options options) { + std::vector<uint32_t> optimized; + + if (!reinterpret_cast<spvtools::Optimizer*>(optimizer)-> + Run(binary, word_count, &optimized, options)) { + return SPV_ERROR_INTERNAL; + } + + auto result_binary = new spv_binary_t(); + if (!result_binary) { + *optimized_binary = nullptr; + return SPV_ERROR_OUT_OF_MEMORY; + } + + result_binary->code = new uint32_t[optimized.size()]; + if (!result_binary->code) { + delete result_binary; + *optimized_binary = nullptr; + return SPV_ERROR_OUT_OF_MEMORY; + } + result_binary->wordCount = optimized.size(); + + memcpy(result_binary->code, optimized.data(), + optimized.size() * sizeof(uint32_t)); + + *optimized_binary = result_binary; + + return SPV_SUCCESS; +} + +} // extern "C"
diff --git a/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp b/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp index 87c9556..6ab1fae 100644 --- a/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp +++ b/third_party/SPIRV-Tools/source/val/validate_bitwise.cpp
@@ -206,13 +206,14 @@ << spvOpcodeString(opcode); const uint32_t base_type = _.GetOperandTypeId(inst, 2); - const uint32_t base_dimension = _.GetDimension(base_type); - const uint32_t result_dimension = _.GetDimension(result_type); if (spv_result_t error = ValidateBaseType(_, inst, base_type)) { return error; } + const uint32_t base_dimension = _.GetDimension(base_type); + const uint32_t result_dimension = _.GetDimension(result_type); + if (base_dimension != result_dimension) return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Expected Base dimension to be equal to Result Type "
diff --git a/third_party/SPIRV-Tools/source/val/validate_type.cpp b/third_party/SPIRV-Tools/source/val/validate_type.cpp index e7adab8..430d819 100644 --- a/third_party/SPIRV-Tools/source/val/validate_type.cpp +++ b/third_party/SPIRV-Tools/source/val/validate_type.cpp
@@ -349,6 +349,15 @@ << ", OpTypeRuntimeArray must only be used for the last member " "of an OpTypeStruct"; } + + if (!_.HasDecoration(inst->id(), spv::Decoration::Block) && + !_.HasDecoration(inst->id(), spv::Decoration::BufferBlock)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << _.VkErrorID(4680) + << spvLogStringForEnv(_.context()->target_env) + << ", OpTypeStruct containing an OpTypeRuntimeArray " + << "must be decorated with Block or BufferBlock."; + } } }
diff --git a/third_party/SPIRV-Tools/test/opt/CMakeLists.txt b/third_party/SPIRV-Tools/test/opt/CMakeLists.txt index af24e65..3b2d384 100644 --- a/third_party/SPIRV-Tools/test/opt/CMakeLists.txt +++ b/third_party/SPIRV-Tools/test/opt/CMakeLists.txt
@@ -21,6 +21,7 @@ analyze_live_input_test.cpp assembly_builder_test.cpp block_merge_test.cpp + c_interface_test.cpp ccp_test.cpp cfg_cleanup_test.cpp cfg_test.cpp
diff --git a/third_party/SPIRV-Tools/test/opt/c_interface_test.cpp b/third_party/SPIRV-Tools/test/opt/c_interface_test.cpp new file mode 100644 index 0000000..a172525 --- /dev/null +++ b/third_party/SPIRV-Tools/test/opt/c_interface_test.cpp
@@ -0,0 +1,534 @@ +// Copyright (c) 2023 Nintendo +// +// 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 <string> +#include <iostream> + +#include "gtest/gtest.h" +#include "spirv-tools/libspirv.h" + +namespace spvtools { +namespace { + +TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForInvalidInput) { + const uint32_t spirv[] = { + 0xDEADFEED, // Invalid Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x01000000, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + // Do not register any passes + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, true); + + spv_binary binary = nullptr; + EXPECT_NE(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_EQ(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, SpecifyConsumerWithValidationNoPassesForInvalidInput) { + const uint32_t spirv[] = { + 0xDEADFEED, // Invalid Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x01000000, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + spvOptimizerSetMessageConsumer( + optimizer, + [](spv_message_level_t, const char*, const spv_position_t*, + const char* message) { + std::cout << message << std::endl; + }); + + // Do not register any passes + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, true); + + testing::internal::CaptureStdout(); + + spv_binary binary = nullptr; + EXPECT_NE(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_EQ(binary, nullptr); + + auto output = testing::internal::GetCapturedStdout(); + EXPECT_STRNE(output.c_str(), ""); + + spvOptimizerOptionsDestroy(options); + + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000001, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + // Do not register any passes + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, true); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Should remain unchanged + EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t)); + EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0); + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerNoPassesForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000003, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001, // GLSL450 + 0x00040015, // OpTypeInt + 0x00000001, // %1 + 0x00000020, // 32 Bits + 0x00000000, // Unsigned + 0x0004002B, // OpConstant + 0x00000001, // %1 + 0x00000002, // %2 + 0x00000001 // 1 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + // Do not register any passes + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, true); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Should remain unchanged + EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t)); + EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0); + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerLegalizationPassesForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000003, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001, // GLSL450 + 0x00040015, // OpTypeInt + 0x00000001, // %1 + 0x00000020, // 32 Bits + 0x00000000, // Unsigned + 0x0004002B, // OpConstant + 0x00000001, // %1 + 0x00000002, // %2 + 0x00000001 // 1 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + spvOptimizerRegisterLegalizationPasses(optimizer); + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, false); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Only check that SPV_SUCCESS is returned, do not verify output + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerPerformancePassesForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000003, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001, // GLSL450 + 0x00040015, // OpTypeInt + 0x00000001, // %1 + 0x00000020, // 32 Bits + 0x00000000, // Unsigned + 0x0004002B, // OpConstant + 0x00000001, // %1 + 0x00000002, // %2 + 0x00000001 // 1 + }; + const uint32_t expected_spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000001, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + spvOptimizerRegisterPerformancePasses(optimizer); + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, false); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Unreferenced OpTypeInt and OpConstant should be removed + EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t)); + EXPECT_EQ(memcmp(binary->code, expected_spirv, + sizeof(expected_spirv) / sizeof(uint32_t)), 0); + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerSizePassesForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000003, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001, // GLSL450 + 0x00040015, // OpTypeInt + 0x00000001, // %1 + 0x00000020, // 32 Bits + 0x00000000, // Unsigned + 0x0004002B, // OpConstant + 0x00000001, // %1 + 0x00000002, // %2 + 0x00000001 // 1 + }; + const uint32_t expected_spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000001, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + spvOptimizerRegisterSizePasses(optimizer); + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, false); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Unreferenced OpTypeInt and OpConstant should be removed + EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t)); + EXPECT_EQ(memcmp(binary->code, expected_spirv, + sizeof(expected_spirv) / sizeof(uint32_t)), 0); + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerPassFromFlagForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000003, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001, // GLSL450 + 0x00040015, // OpTypeInt + 0x00000001, // %1 + 0x00000020, // 32 Bits + 0x00000000, // Unsigned + 0x0004002B, // OpConstant + 0x00000001, // %1 + 0x00000002, // %2 + 0x00000001 // 1 + }; + const uint32_t expected_spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000001, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + EXPECT_TRUE(spvOptimizerRegisterPassFromFlag( + optimizer, "--eliminate-dead-code-aggressive")); + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, false); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Unreferenced OpTypeInt and OpConstant should be removed + EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t)); + EXPECT_EQ(memcmp(binary->code, expected_spirv, + sizeof(expected_spirv) / sizeof(uint32_t)), 0); + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerPassesFromFlagsForValidInput) { + const uint32_t spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000003, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001, // GLSL450 + 0x00040015, // OpTypeInt + 0x00000001, // %1 + 0x00000020, // 32 Bits + 0x00000000, // Unsigned + 0x0004002B, // OpConstant + 0x00000001, // %1 + 0x00000002, // %2 + 0x00000001 // 1 + }; + const uint32_t expected_spirv[] = { + 0x07230203, // Magic + 0x00010100, // Version 1.1 + 0x00000000, // No Generator + 0x00000001, // Bound + 0x00000000, // Schema + 0x00020011, // OpCapability + 0x00000001, // Shader + 0x00020011, // OpCapability + 0x00000005, // Linkage + 0x0003000E, // OpMemoryModel + 0x00000000, // Logical + 0x00000001 // GLSL450 + }; + + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + const char* flags[2] = { + "--eliminate-dead-const", + "--eliminate-dead-code-aggressive" + }; + + EXPECT_TRUE(spvOptimizerRegisterPassesFromFlags( + optimizer, flags, sizeof(flags) / sizeof(const char*))); + + auto options = spvOptimizerOptionsCreate(); + ASSERT_NE(options, nullptr); + spvOptimizerOptionsSetRunValidator(options, false); + + spv_binary binary = nullptr; + EXPECT_EQ(SPV_SUCCESS, + spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t), + &binary, options)); + ASSERT_NE(binary, nullptr); + + spvOptimizerOptionsDestroy(options); + + // Unreferenced OpTypeInt and OpConstant should be removed + EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t)); + EXPECT_EQ(memcmp(binary->code, expected_spirv, + sizeof(expected_spirv) / sizeof(uint32_t)), 0); + + spvBinaryDestroy(binary); + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerInvalidPassFromFlag) { + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + EXPECT_FALSE(spvOptimizerRegisterPassFromFlag( + optimizer, "--this-is-not-a-valid-pass")); + + spvOptimizerDestroy(optimizer); +} + +TEST(OptimizerCInterface, DefaultConsumerInvalidPassesFromFlags) { + auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1); + ASSERT_NE(optimizer, nullptr); + + const char* flags[2] = { + "--eliminate-dead-const", + "--this-is-not-a-valid-pass" + }; + + EXPECT_FALSE(spvOptimizerRegisterPassesFromFlags( + optimizer, flags, sizeof(flags) / sizeof(const char*))); + + spvOptimizerDestroy(optimizer); +} + +} // namespace +} // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/opt/fold_test.cpp b/third_party/SPIRV-Tools/test/opt/fold_test.cpp index 06b91f3..cc9bcd6 100644 --- a/third_party/SPIRV-Tools/test/opt/fold_test.cpp +++ b/third_party/SPIRV-Tools/test/opt/fold_test.cpp
@@ -7363,7 +7363,16 @@ "%5 = OpCompositeConstruct %v2int %3 %4\n" + "OpReturn\n" + "OpFunctionEnd", - 5, true) + 5, true), + // Test case 16: Don't fold when type cannot be deduced to a constant. + InstructionFoldingCase<bool>( + Header() + + "%main = OpFunction %void None %void_func\n" + + "%main_lab = OpLabel\n" + + "%4 = OpCompositeInsert %struct_v2int_int_int %int_1 %struct_v2int_int_int_null 2\n" + + "OpReturn\n" + + "OpFunctionEnd", + 4, false) )); INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
diff --git a/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp index 3600d0d..d450511 100644 --- a/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp +++ b/third_party/SPIRV-Tools/test/opt/inst_bindless_check_test.cpp
@@ -1040,10 +1040,6 @@ %i_vTextureCoords = OpVariable %_ptr_Input_v2int Input %_ptr_Output_v4float = OpTypePointer Output %v4float %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -; CHECK: uint_0 = OpConstant %uint 0 -; CHECK: bool = OpTypeBool -; CHECK: %41 = OpTypeFunction %void %uint %uint %uint %uint -; CHECK: _runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float @@ -2385,14 +2381,7 @@ %_ptr_Input_float = OpTypePointer Input %float %b = OpVariable %_ptr_Input_float Input %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %uint = OpTypeInt 32 0 -; CHECK: %26 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -; CHECK: %48 = OpTypeFunction %void %uint %uint %uint %uint -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input ; CHECK: %v4uint = OpTypeVector %uint 4 ; CHECK: %102 = OpTypeFunction %uint %uint %uint %uint %uint @@ -2508,10 +2497,7 @@ %nu_ii = OpVariable %_ptr_Input_int Input %int_0 = OpConstant %int 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %bool = OpTypeBool -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint ; CHECK: %v4float = OpTypeVector %float 4 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input @@ -2637,11 +2623,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: %v3uint = OpTypeVector %uint 3 ; CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint ; CHECK: %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input @@ -2797,12 +2779,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %34 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float ; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint )"; @@ -2954,12 +2931,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %34 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float ; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint @@ -3112,12 +3084,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %34 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float ; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint @@ -3270,12 +3237,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %34 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float ; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint @@ -3428,12 +3390,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %34 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float ; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint @@ -3586,12 +3543,7 @@ %v4float = OpTypeVector %float 4 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float -; CHECK: %34 = OpTypeFunction %uint %uint %uint -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -; CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float ; CHECK: [[null_uint:%\w+]] = OpConstantNull %uint )"; @@ -3777,8 +3729,6 @@ %_ptr_Output_v4float = OpTypePointer Output %v4float %outColor = OpVariable %_ptr_Output_v4float Output %float_0 = OpConstant %float 0 -; CHECK: %bool = OpTypeBool -; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( ; CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float )" + kInputGlobals + R"( @@ -3963,11 +3913,7 @@ %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input %_ptr_Output_v4float = OpTypePointer Output %v4float %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output - ;CHECK: %122 = OpTypeFunction %uint %uint %uint %uint - ;CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint - )" + kInputGlobals + R"( - ;CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint - )" + kOutputGlobals + R"( + )" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input ;CHECK: %v4uint = OpTypeVector %uint 4 @@ -4154,12 +4100,7 @@ %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input %_ptr_Output_v4float = OpTypePointer Output %v4float %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -;CHECK: %105 = OpTypeFunction %uint %uint %uint %uint -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -;CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input ;CHECK: %v4uint = OpTypeVector %uint 4 @@ -4296,12 +4237,7 @@ %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input %_ptr_Output_v4float = OpTypePointer Output %v4float %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -;CHECK: %104 = OpTypeFunction %uint %uint %uint %uint %uint -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -;CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input ;CHECK: %v4uint = OpTypeVector %uint 4 @@ -4436,10 +4372,7 @@ %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input %_ptr_Output_v4float = OpTypePointer Output %v4float %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -;CHECK: %bool = OpTypeBool -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input ;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float @@ -4620,12 +4553,7 @@ %i_vTextureCoords = OpVariable %_ptr_Input_v2float Input %_ptr_Output_v4float = OpTypePointer Output %v4float %_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output -;CHECK: %61 = OpTypeFunction %uint %uint %uint %uint -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -;CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float ;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input ;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float @@ -4750,12 +4678,7 @@ %v4float = OpTypeVector %float 4 %_ptr_Input_v4float = OpTypePointer Input %v4float %a_position = OpVariable %_ptr_Input_v4float Input -;CHECK: %37 = OpTypeFunction %uint %uint %uint %uint -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -;CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input @@ -4873,12 +4796,7 @@ %v4float = OpTypeVector %float 4 %_ptr_Input_v4float = OpTypePointer Input %v4float %a_position = OpVariable %_ptr_Input_v4float Input -;CHECK: %37 = OpTypeFunction %uint %uint %uint %uint -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -;CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input @@ -5003,12 +4921,7 @@ %v4float = OpTypeVector %float 4 %_ptr_Input_v4float = OpTypePointer Input %v4float %a_position = OpVariable %_ptr_Input_v4float Input -;CHECK: %46 = OpTypeFunction %uint %uint %uint %uint -;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint -)" + kInputGlobals + R"( -;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint -;CHECK: %bool = OpTypeBool -)" + kOutputGlobals + R"( +)" + kInputGlobals + kOutputGlobals + R"( ;CHECK:%_ptr_Input_uint = OpTypePointer Input %uint ;CHECK:%gl_VertexIndex = OpVariable %_ptr_Input_uint Input ;CHECK:%gl_InstanceIndex = OpVariable %_ptr_Input_uint Input @@ -5202,7 +5115,7 @@ %x = OpVariable %_ptr_Output_v4float Output ;CHECK: %uint = OpTypeInt 32 0 ;CHECK: %bool = OpTypeBool -;CHECK: %34 = OpTypeFunction %void %uint %uint %uint %uint %uint +;CHECK: {{%\w+}} = OpTypeFunction %void %uint %uint %uint %uint %uint ;CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( ;CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
diff --git a/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp index b08f7b0..4a56f60 100644 --- a/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp +++ b/third_party/SPIRV-Tools/test/opt/inst_buff_addr_check_test.cpp
@@ -272,7 +272,7 @@ ; CHECK: %_runtimearr_ulong = OpTypeRuntimeArray %ulong )" + kInputGlobals + R"( ; CHECK: %_ptr_StorageBuffer_ulong = OpTypePointer StorageBuffer %ulong -; CHECK: %70 = OpTypeFunction %void %uint %uint %uint %uint +; CHECK: {{%\w+}} = OpTypeFunction %void %uint %uint %uint %uint ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint @@ -524,7 +524,7 @@ %ulong_18446744073172680704 = OpConstant %ulong 18446744073172680704 ; CHECK: %47 = OpTypeFunction %bool %ulong %uint )" + kInputGlobals + R"( -; CHECK: %90 = OpTypeFunction %void %uint %uint %uint %uint +; CHECK: {{%\w+}} = OpTypeFunction %void %uint %uint %uint %uint )" + kOutputGlobals + R"( ; CHECK: %143 = OpConstantNull %Test_0 )";
diff --git a/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp b/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp index 6a4cbdd..4031480 100644 --- a/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp +++ b/third_party/SPIRV-Tools/test/opt/inst_debug_printf_test.cpp
@@ -111,7 +111,7 @@ %_ptr_Output_v4float = OpTypePointer Output %v4float %4 = OpVariable %_ptr_Output_v4float Output ; CHECK: %uint = OpTypeInt 32 0 -; CHECK: %38 = OpTypeFunction %void %uint %uint %uint %uint %uint %uint +; CHECK: [[func_type:%\w+]] = OpTypeFunction %void %uint %uint %uint %uint %uint %uint ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint )" + kOutputGlobals + R"( ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint @@ -149,7 +149,7 @@ )"; const std::string output_func = R"( -; CHECK: %inst_printf_stream_write_6 = OpFunction %void None %38 +; CHECK: %inst_printf_stream_write_6 = OpFunction %void None [[func_type]] ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint ; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
diff --git a/third_party/SPIRV-Tools/test/val/val_bitwise_test.cpp b/third_party/SPIRV-Tools/test/val/val_bitwise_test.cpp index bebaa84..b849e7b 100644 --- a/third_party/SPIRV-Tools/test/val/val_bitwise_test.cpp +++ b/third_party/SPIRV-Tools/test/val/val_bitwise_test.cpp
@@ -643,6 +643,32 @@ HasSubstr("Expected 32-bit int type for Base operand: BitCount")); } +TEST_F(ValidateBitwise, OpBitCountPointer) { + const std::string body = R"( +OpCapability Shader +OpMemoryModel Logical GLSL450 +OpEntryPoint GLCompute %main "main" +OpExecutionMode %main LocalSize 1 1 1 +%void = OpTypeVoid +%int = OpTypeInt 32 0 +%ptr_int = OpTypePointer Function %int +%void_fn = OpTypeFunction %void +%main = OpFunction %void None %void_fn +%entry = OpLabel +%var = OpVariable %ptr_int Function +%count = OpBitCount %int %var +OpReturn +OpFunctionEnd +)"; + + CompileSuccessfully(body); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "Expected int scalar or vector type for Base operand: BitCount")); +} + } // namespace } // namespace val } // namespace spvtools
diff --git a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp index 04d373a..4f90e6b 100644 --- a/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp +++ b/third_party/SPIRV-Tools/test/val/val_decoration_test.cpp
@@ -5281,6 +5281,37 @@ "rules: member 1 at offset 1 is not aligned to 4")); } +TEST_F(ValidateDecorations, VulkanStructWithoutDecorationWithRuntimeArray) { + std::string str = R"( + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %func "func" + OpExecutionMode %func OriginUpperLeft + OpDecorate %array_t ArrayStride 4 + OpMemberDecorate %struct_t 0 Offset 0 + OpMemberDecorate %struct_t 1 Offset 4 + %uint_t = OpTypeInt 32 0 + %array_t = OpTypeRuntimeArray %uint_t + %struct_t = OpTypeStruct %uint_t %array_t +%struct_ptr = OpTypePointer StorageBuffer %struct_t + %2 = OpVariable %struct_ptr StorageBuffer + %void = OpTypeVoid + %func_t = OpTypeFunction %void + %func = OpFunction %void None %func_t + %1 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1); + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Vulkan, OpTypeStruct containing an OpTypeRuntimeArray " + "must be decorated with Block or BufferBlock.")); +} + TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) { const std::string spirv = R"( OpCapability Shader
diff --git a/third_party/SPIRV-Tools/test/val/val_memory_test.cpp b/third_party/SPIRV-Tools/test/val/val_memory_test.cpp index d0735dc..d575318 100644 --- a/third_party/SPIRV-Tools/test/val/val_memory_test.cpp +++ b/third_party/SPIRV-Tools/test/val/val_memory_test.cpp
@@ -2475,6 +2475,7 @@ OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %func "func" OpExecutionMode %func OriginUpperLeft +OpDecorate %struct_t Block %uint_t = OpTypeInt 32 0 %array_t = OpTypeRuntimeArray %uint_t %struct_t = OpTypeStruct %array_t @@ -2498,7 +2499,7 @@ "For Vulkan, OpTypeStruct variables containing OpTypeRuntimeArray " "must have storage class of StorageBuffer, PhysicalStorageBuffer, or " "Uniform.\n %6 = " - "OpVariable %_ptr_Workgroup__struct_4 Workgroup\n")); + "OpVariable %_ptr_Workgroup__struct_2 Workgroup\n")); } TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructWithoutBlockBad) { @@ -2507,6 +2508,7 @@ OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %func "func" OpExecutionMode %func OriginUpperLeft +OpDecorate %struct_t BufferBlock %uint_t = OpTypeInt 32 0 %array_t = OpTypeRuntimeArray %uint_t %struct_t = OpTypeStruct %array_t @@ -2529,7 +2531,7 @@ "OpTypeRuntimeArray must be decorated with Block if it " "has storage class StorageBuffer or " "PhysicalStorageBuffer.\n %6 = OpVariable " - "%_ptr_StorageBuffer__struct_4 StorageBuffer\n")); + "%_ptr_StorageBuffer__struct_2 StorageBuffer\n")); } TEST_F(ValidateMemory, VulkanRTAInsideUniformStructGood) { @@ -2564,6 +2566,7 @@ OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %func "func" OpExecutionMode %func OriginUpperLeft +OpDecorate %struct_t Block %uint_t = OpTypeInt 32 0 %array_t = OpTypeRuntimeArray %uint_t %struct_t = OpTypeStruct %array_t @@ -2585,7 +2588,7 @@ HasSubstr("For Vulkan, an OpTypeStruct variable containing an " "OpTypeRuntimeArray must be decorated with BufferBlock " "if it has storage class Uniform.\n %6 = OpVariable " - "%_ptr_Uniform__struct_4 Uniform\n")); + "%_ptr_Uniform__struct_2 Uniform\n")); } TEST_F(ValidateMemory, VulkanRTAInsideRTABad) {
diff --git a/third_party/SPIRV-Tools/utils/check_copyright.py b/third_party/SPIRV-Tools/utils/check_copyright.py index aa647af..e3e74bc 100755 --- a/third_party/SPIRV-Tools/utils/check_copyright.py +++ b/third_party/SPIRV-Tools/utils/check_copyright.py
@@ -41,8 +41,9 @@ 'Alastair F. Donaldson', 'Mostafa Ashraf', 'Shiyu Liu', - 'ZHOU He'] -CURRENT_YEAR = 2022 + 'ZHOU He', + 'Nintendo'] +CURRENT_YEAR = 2023 FIRST_YEAR = 2014 FINAL_YEAR = CURRENT_YEAR + 5
diff --git a/third_party/SPIRV-Tools/utils/roll_deps.sh b/third_party/SPIRV-Tools/utils/roll_deps.sh index bf6d693..6289c94 100755 --- a/third_party/SPIRV-Tools/utils/roll_deps.sh +++ b/third_party/SPIRV-Tools/utils/roll_deps.sh
@@ -31,7 +31,7 @@ # We are not rolling google test for now. The latest version requires C++14. dependencies=("external/effcee/" -# "external/googletest/") + "external/googletest/" "external/re2/" "external/spirv-headers/")
diff --git a/third_party/SPIRV-Tools/utils/update_build_version.py b/third_party/SPIRV-Tools/utils/update_build_version.py index b1c7b21..ec475ea 100755 --- a/third_party/SPIRV-Tools/utils/update_build_version.py +++ b/third_party/SPIRV-Tools/utils/update_build_version.py
@@ -17,16 +17,13 @@ # Updates an output file with version info unless the new content is the same # as the existing content. # -# Args: <changes-file> <output-file> +# Args: <repo-path> <output-file> # # The output file will contain a line of text consisting of two C source syntax # string literals separated by a comma: -# - The software version deduced from the given CHANGES file. +# - The software version deduced from the last release tag. # - A longer string with the project name, the software version number, and -# git commit information for the CHANGES file's directory. The commit -# information is the output of "git describe" if that succeeds, or "git -# rev-parse HEAD" if that succeeds, or otherwise a message containing the -# phrase "unknown hash". +# git commit information for this release. # The string contents are escaped as necessary. import datetime @@ -39,6 +36,13 @@ import sys import time +# Regex to match the SPIR-V version tag. +# Example of matching tags: +# - v2020.1 +# - v2020.1-dev +# - v2020.1.rc1 +VERSION_REGEX = re.compile(r'^v(\d+)\.(\d+)(-dev|rc\d+)?$') + # Format of the output generated by this script. Example: # "v2023.1", "SPIRV-Tools v2023.1 0fc5526f2b01a0cc89192c10cf8bef77f1007a62, 2023-01-18T14:51:49" OUTPUT_FORMAT = '"{version_tag}", "SPIRV-Tools {version_tag} {description}"\n' @@ -79,38 +83,66 @@ return False, None return p.returncode == 0, stdout -def deduce_software_version(changes_file): - """Returns a tuple (success, software version number) parsed from the - given CHANGES file. +def deduce_last_release(repo_path): + """Returns a software version number parsed from git tags.""" - Success is set to True if the software version could be deduced. - Software version is undefined if success if False. - Function expects the CHANGES file to describes most recent versions first. - """ + success, tag_list = command_output(['git', 'tag', '--sort=-v:refname'], repo_path) + if not success: + return False, None - # Match the first well-formed version-and-date line - # Allow trailing whitespace in the checked-out source code has - # unexpected carriage returns on a linefeed-only system such as - # Linux. - pattern = re.compile(r'^(v\d+\.\d+(-dev)?) \d\d\d\d-\d\d-\d\d\s*$') - with open(changes_file, mode='r') as f: - for line in f.readlines(): - match = pattern.match(line) - if match: - return True, match.group(1) + latest_version_tag = None + for tag in tag_list.decode().splitlines(): + if VERSION_REGEX.match(tag): + latest_version_tag = tag + break + + if latest_version_tag is None: + logging.error("No tag matching version regex matching.") + return False, None + return True, latest_version_tag + +def get_last_release_tuple(repo_path): + success, version = deduce_last_release(repo_path) + if not success: return False, None + m = VERSION_REGEX.match(version) + if len(m.groups()) != 3: + return False, None + return True, (int(m.groups()[0]), int(m.groups()[1])) -def describe(repo_path): +def deduce_current_release(repo_path): + status, version_tuple = get_last_release_tuple(repo_path) + if not status: + return False, None + + last_release_tag = "v{}.{}-dev".format(*version_tuple) + success, tag_list = command_output(['git', 'tag', '--contains'], repo_path) + if success: + if last_release_tag in set(tag_list.decode().splitlines()): + return True, last_release_tag + else: + logging.warning("Could not check tags for commit. Assuming -dev version.") + + now_year = datetime.datetime.now().year + if version_tuple[0] == now_year: + version_tuple = (now_year, version_tuple[1] + 1) + else: + version_tuple = (now_year, 1) + + return True, "v{}.{}-dev".format(*version_tuple) + +def get_description_for_head(repo_path): """Returns a string describing the current Git HEAD version as descriptively - as possible. - - Runs 'git describe', or alternately 'git rev-parse HEAD', in directory. If - successful, returns the output; otherwise returns 'unknown hash, <date>'.""" + as possible, in order of priority: + - git describe output + - git rev-parse HEAD output + - "unknown-hash, <date>" + """ success, output = command_output(['git', 'describe'], repo_path) if not success: - output = command_output(['git', 'rev-parse', 'HEAD'], repo_path) + success, output = command_output(['git', 'rev-parse', 'HEAD'], repo_path) if success: # decode() is needed here for Python3 compatibility. In Python2, @@ -126,9 +158,12 @@ # reproducible builds, allow the builder to override the wall # clock time with environment variable SOURCE_DATE_EPOCH # containing a (presumably) fixed timestamp. - timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) - iso_date = datetime.datetime.utcfromtimestamp(timestamp).isoformat() - return "unknown hash, {}".format(iso_date) + if 'SOURCE_DATE_EPOCH' in os.environ: + timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) + iso_date = datetime.datetime.utcfromtimestamp(timestamp).isoformat() + else: + iso_date = datetime.datetime.now().isoformat() + return "unknown_hash, {}".format(iso_date) def main(): FORMAT = '%(asctime)s %(message)s' @@ -137,16 +172,15 @@ logging.error("usage: {} <repo-path> <output-file>".format(sys.argv[0])) sys.exit(1) - changes_file_path = os.path.realpath(sys.argv[1]) + repo_path = os.path.realpath(sys.argv[1]) output_file_path = sys.argv[2] - success, version = deduce_software_version(changes_file_path) + success, version = deduce_current_release(repo_path) if not success: - logging.error("Could not deduce latest release version from {}.".format(changes_file_path)) - sys.exit(1) + logging.warning("Could not deduce latest release version from history.") + version = "unknown_version" - repo_path = os.path.dirname(changes_file_path) - description = describe(repo_path) + description = get_description_for_head(repo_path) content = OUTPUT_FORMAT.format(version_tag=version, description=description) # Escape file content.