New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The spirv-opt remove-duplicates pass makes a seemingly erroneous transformation of my shader #1372
Comments
I should add that the ultimate result is that performing reflection on the optimised SPIR-V results in incorrect set and binding point decorations for the uniform blocks. Which leads to the validation layers emitting for example:
|
Thanks for opening the bug. We will look into it. Without looking in detail, the remove duplicates looks for types that are the same except for the name, and merges them into one. That is what you see happening. We will be in touch if we need more information. |
Thanks. That seems a bit odd to me if the layout specifiers are different, but perhaps I'm missing something. |
The layout specifiers are applied to the variables, not to the types, so merging the types should not impact those layout specifiers (and looking at the optimised SPIR-V binary, the layout specifiers are still properly applied). |
Re-reading the specification, 1) we can’t have multiple times the same non-aggregate type, and 2) even though we can have multiple times the same aggregate type, they are still considered to be different types. So, if we disregard binaries produced during linking, there should never be duplicate types; removing duplicate types should probably be only run after linking multiple SPIR-V modules together. |
The reason we put this in is when we have two types that are that have the exact same layout and decorations, the TypeManager can get confused. Just because spec allows multiple isomorphic types, does it say it is wrong to replace one with the other? What is the semantic difference? It allows one object to be copied to another, but I do not know how it changes. Obviously, we should remove the extra OpName instruction when we merge two types. I can get that done on Monday. However, I'd like to understand the fundamental problem. Based on the error message, it looks like we are not removing a variable that is removed when we don't run remove duplicates. The error message seems to say that a descriptor slot is used, but it is not part of the pipeline layout. This looks like it is related to the decorations attached to the variables. |
I wonder if it’s not the reflection code which is getting confused by something in the binary without duplicates, because the errors are about both variables, not just one of them; I don’t see anything weird with that binary.
Just curious, are you planning to just keep the first one and remove all others? |
@pierremoreau I forget the code now, but at the point that you remove the decorations for one type, you should remove it's name as well. Whatever we do to remove the decorations should be replaced by a call to RemoveNamesAndDecorates. At least that is my guess. |
I am starting to suspect that the manner in which I am performing the SPIR-V reflection is incorrect. |
Then again, looking at it further, that transformation seems to make it impossible to perform the reflection. Is the solution to perform reflection prior to optimisation? I can imagine that other optimiser transformations would invalidate such reflection, though. |
I've been reading about this a little. @StrayLightning, can you run an experiment for me? Take the original shader that works, and manually change the spir-v to remove the OpName instructions. Let me know if that new shader still works. If that works, can you replace the types on the OpVariable instructions for the uniform object so they have the same type. I want to try to narrow down the change that actually makes a difference. It is that the the OpName for the types are used, or is it expecting every OpVariable instruction in the uniform storage class to have a different type. |
I don't think you are doing anything wrong. Do not do reflection before optimization. That can cause other problems, as you pointed out. I think the problem is a disconnect between what spirv-opt thinks is valid spir-v and what the reflection code expects. |
After commenting the following in the unoptimised SPIR-V:
The shader reflection now shows the uniform block with the name _56_57, which means that the application doesn't know anything about "atmosphere_fragment_uniforms" and fails. If, instead of the above, I change:
To:
(I've done it this way around because of the order of things in the SPIR-V assembly: spirv-opt does the transform the other way around.) In this case the reflection indicates two blocks with the name "atmosphere_fragment_uniforms" and the application can't reflect on "planet_dynamic_uniforms". So the reflection seems to be reliant on both the OpName being present and the types of the uniform blocks, which seems a bit awkward from the point of view of de-duplicating types. I hope this is of use. |
This is of use. At this point I have to say that the reflection code is wrong or there is a problem in the spec. The spir-v spec, referring to OpName instructions, says "This has no semantic impact and can safely be removed from a module." (https://www.khronos.org/registry/spir-v/specs/1.2/SPIRV.html#OpName). The reflection code should not be relying on an OpName. This now goes beyond my knowledge. @dneto0 Do you now anything about this? |
I only had a quick look at the reflection code (plus I have never done any Rust before, so I might have misunderstood a few things in that code), but it seems that the reflection code is processing the SPIR-V (in some tree form), in order to discover the uniform blocks and other similar data, and you then use that knowledge to fill in the descriptor sets. Is this what is happening, or is there more to it? If not, then to achieve that, you shouldn’t need the names; Vulkan does not seem to ask for variable names either in its descriptor sets. |
The merging types we do not remove other information related to the types. We simply leave it duplicated, and hope it is removed later. This is what happens with decorations. They are removed in the next phase of remove duplicates. However, for OpNames that is not the case. We end up with two different names for the same id, which does not make sense. The solution is to remove the names and decorations for the type being removed instead of rewriting them to refer to the other type. Note that it is possible that if the first type does not have a name, then the types will end up with no name. That is fine because the names should not have any semantic significance anyway. The was identified in issue KhronosGroup#1372, but this does not fix that issue.
The application lays out uniform buffers in memory to be vkMapMemory'd onto the GPU. In order to know what to place where, the application reflects the SPIR-V based on uniform block name and uniform offset (amongst other things.) It is true that the identifiers are not required to be handed on to Vulkan, but things like binding points are. If something is truly dead and can be removed by optimisation of SPIR-V it makes sense that the application should be able to handle that case. In the case that the entity is alive, however, it's reasonable that the application can perform reflection on the shader, with the names used by the shader, in order to work out what goes where. Again, there might well be things I am doing wrong with the GLSL, Vulkan, or the reflection that is not valid. There may well be better ways of achieving the same thing, but this is the model that I've come to from investigating what Vulkan developers say they do with their shader processing pipelines. I am aware that this is probably consuming effort which might well be better spent elsewhere, and the problem might well be with how SPIRV-Cross is performing reflection, or how my application is using that information, or my shaders... My solution is to disable SPIR-V optimisation for now, and I'm happy with that. Many thanks for spending what time you already have looking at this. On the flip side, I am more than happy to provide additional information or dig into this in my own time (because it is interesting.) It probably doesn't make any sense to try to understand the specifics of the reflection in my application, but in case you happened to be interested:
|
Ah, I hadn’t seen you were using SPIRV-Cross for the reflection. I’ll try to get the whole stack running and trace down which part of the reflection is relying on OpName; I don’t know when I will have time to do that though, but hopefully before next week.
Right, and the binding points and sets are still properly set AFAICS. |
Though not under the same names as the un-optimised SPIR-V. FWIW, I've been using such as the following to short-cut inspection of the transformed SPIR-V:
|
That is true, however if the reflection is iterating over the variables rather than the names, then it is not an issue (the binding point and set are attached to the ID of the variable). Thanks for the short-cut. |
The merging types we do not remove other information related to the types. We simply leave it duplicated, and hope it is removed later. This is what happens with decorations. They are removed in the next phase of remove duplicates. However, for OpNames that is not the case. We end up with two different names for the same id, which does not make sense. The solution is to remove the names and decorations for the type being removed instead of rewriting them to refer to the other type. Note that it is possible that if the first type does not have a name, then the types will end up with no name. That is fine because the names should not have any semantic significance anyway. The was identified in issue #1372, but this does not fix that issue.
When doing reflection users care about the names of the variable, the name of the type, and the name of the members. Remove duplicates breaks this because it removes the names one of the types when merging. To fix this we have to keep the different types around for each resource. This commit adds code to remove duplicates to look for the types uses to describe resources, and make sure they do not get merged. This could have a negative effect on compile time, but it was not expected to be much. Fixes KhronosGroup#1372.
* Update external/shaderc/glslang from branch 'master-ndk' to 2a7bb558a86e95ea34fe537c5b8b22cd04101e82 - Merge remote-tracking branch 'aosp/upstream-master' into update-shaderc Includes: 806af25f Merge pull request #1442 from dneto0/use-forked-android-ndk-repo e7f9caea Errors and Build: Fix build warnings, which also improved error messages. 4aeca2df NDK build: Use NDK r17b and its own CMake toolchain file b75c7065 Travis CI: Fix comments disabling code. e5b27660 Merge pull request #1440 from dneto0/later-android 3541d8a5 Travis-CI: Use Android NDK r13b specifically 8dafeab4 Merge pull request #1438 from Think-Silicon/getUniformStages 0ea33a26 Non-functional: Retrigger bots; the previous failure looks suspicious. cf6bd066 HLSL: Fix #1432: Globally initialize local static variables. f556e5da Reflection exposes the Shader Stages where a Uniform is present 64315a8a Merge pull request #1434 from antiagainst/fix-spirv-tools-header a2c39a29 Use public SPIRV-Tools header cd57b4ba Merge pull request #1431 from KhronosGroup/implement-8-16-bit-storage 312dcfb0 Implement GL_EXT_shader_16bit_storage and GL_EXT_shader_8bit_storage extensions. eefab240 Bump revision. dccfeedf HLSL: Fix #1423: implement CalculateLevelOfDetailUnclamped(). ab8960fd Merge pull request #1416 from aejsmith/samplerless-texture-functions 513cc4cf Merge branch 'HaydnTrigg-patch-1' c88edb13 Merge branch 'patch-1' of https://github.com/HaydnTrigg/glslang into HaydnTrigg-patch-1 5e701954 Merge pull request #1420 from KhronosGroup/spir-dis e2156222 SPV: Add option to print disassembly in standard form using SPIRV-Tools. 6d61684f Bump revision. 802c62bc PP: Rationalize return values of MacroExpand. 9cc81de0 PP/HLSL: Fix #1424: support comma in nested curly braces for macro arg e47bfaed Add support for GL_EXT_samplerless_texture_functions e826286f Constant.cpp Floating point divide by zero 0b964b3c Merge pull request #1419 from tgjones/spirv-remap-artifact 9177e05f Include spirv-remap.exe in AppVeyor artifacts ef1f899b Merge pull request #1413 from karl-lunarg/fix-update fa403b96 script: Improve update sources script 16cf5a5d Merge pull request #1411 from KhronosGroup/fix-literal-warnings 866f6714 Build: Make literal casting have fewer warnings and be more consistent. 5fe506a8 Merge pull request #1409 from greg-lunarg/remap3 c6831d1e Add support for OpConstantNull and OpConstantSampler to spirv-remap c99304c5 Bump revision. 2a805d9c Revert "GLSL: Fix #1279: refract does not have a double-type eta." bea08fe0 Merge pull request #1405 from Igalia/nroberts/amb-arrays 1d024b53 Take into account arrays of opaque types when reserving bindings 2c8265bb GLSL: Fix #1358: Support "struct name", where name could be a user type 1ea8f595 Merge pull request #1402 from greg-lunarg/kg21 ff50b9fb Update spirv-tools known-good 7dc1a989 Merge pull request #1401 from dneto0/bad-e11 617d1b12 Relax a stringToDouble test for, OSX AppleClang 9.1 ba018e67 SPV: Fix #1399 emit ImageGatherExtended when using ConstOffsets operand ad7645f4 Fix #1360: uint->int width conversions must still be typed as uint. 14b85d3f Fix #1395: GLSL volatile maps to SPIR-V Volatile and Coherent. d6c97557 Change the major revision number for next commit. a7eb582a Bump revision. 9c3fde7f Merge pull request #1397 from LoopDawg/warning-fix-4 470a68cf Fix several signed/unsigned comparison compile warnings. Testing: checkbuild.py on Linux; unit tests on Windows Change-Id: Ifd09865436af7b700f235c7e93a83f208d63c69b - Merge pull request #1442 from dneto0/use-forked-android-ndk-repo NDK build: Use NDK r17b and its own CMake toolchain file - Errors and Build: Fix build warnings, which also improved error messages. - NDK build: Use NDK r17b and its own CMake toolchain file More recent NDK releases have their own CMake toolchain file. Use it. Also, download the NDK from github.com:dneto0/android-ndk. That is a fork of the repo we used to use, but we have more control over how long it stays stable. - Travis CI: Fix comments disabling code. - Merge pull request #1440 from dneto0/later-android WIP: Travis-CI: Use Android NDK r13b specifically - Travis-CI: Use Android NDK r13b specifically The Travis-CI bot downloads a copy of the Android NDK. The source we get it from recently updated to Android NDK r17b. However, the android.toolchain.cmake file does not know how to parse the Android native API level from that version of the NDK. So check out the NDK r13b version that we were using until yesterday. Fixes #1439 - Merge pull request #1438 from Think-Silicon/getUniformStages Reflection exposes the Shader Stages where a Uniform is present - Non-functional: Retrigger bots; the previous failure looks suspicious. - HLSL: Fix #1432: Globally initialize local static variables. - Reflection exposes the Shader Stages where a Uniform is present - Merge pull request #1434 from antiagainst/fix-spirv-tools-header Use public SPIRV-Tools header - Use public SPIRV-Tools header - Merge pull request #1431 from KhronosGroup/implement-8-16-bit-storage Implement GL_EXT_shader_16bit_storage and GL_EXT_shader_8bit_storage … - Implement GL_EXT_shader_16bit_storage and GL_EXT_shader_8bit_storage extensions. These introduce limited support for 8/16-bit types such that they can only be accessed in buffer memory and converted to/from 32-bit types. Contributed from Khronos-internal work. - Bump revision. - HLSL: Fix #1423: implement CalculateLevelOfDetailUnclamped(). (If there is a bias issue, we need to discover what it is.) - Merge pull request #1416 from aejsmith/samplerless-texture-functions Add support for GL_EXT_samplerless_texture_functions - Merge branch 'HaydnTrigg-patch-1' - Merge branch 'patch-1' of https://github.com/HaydnTrigg/glslang into HaydnTrigg-patch-1 - Merge pull request #1420 from KhronosGroup/spir-dis SPV: Add option to print disassembly in standard form using SPIRV-Tools. - SPV: Add option to print disassembly in standard form using SPIRV-Tools. - Bump revision. - PP: Rationalize return values of MacroExpand. This results in better error recovery, including fewer crashes on badly formed PP input. - PP/HLSL: Fix #1424: support comma in nested curly braces for macro arg - Add support for GL_EXT_samplerless_texture_functions - Constant.cpp Floating point divide by zero Constant.cpp will throw a floating point divide by zero if floating point exceptions are enabled in Win32 causing the program to crash. This fix manually checks the right-hand argument of the division and sets appropriate Infinity, Negative Infinity, or NAN as if the floating point exceptions were disabled. - Merge pull request #1419 from tgjones/spirv-remap-artifact Include spirv-remap.exe in AppVeyor artifacts - Include spirv-remap.exe in AppVeyor artifacts - Merge pull request #1413 from karl-lunarg/fix-update script: Improve update sources script - script: Improve update sources script - remove unused variable to pass pylint - Use another approach to detect if known-good remote is already present to avoid the need for "ignore following errors" message. - Merge pull request #1411 from KhronosGroup/fix-literal-warnings Build: Make literal casting have fewer warnings and be more consistent. - Build: Make literal casting have fewer warnings and be more consistent. - Merge pull request #1409 from greg-lunarg/remap3 Add support for OpConstantNull and OpConstantSampler to spirv-remap - Add support for OpConstantNull and OpConstantSampler to spirv-remap Fixes issue #1408 - Bump revision. - Revert "GLSL: Fix #1279: refract does not have a double-type eta." This reverts commit ebec909487b8c44a8c28b40c9899857593cc9bb5. Khronos decided glslang was originally correct, and the specifications are incorrect. - Merge pull request #1405 from Igalia/nroberts/amb-arrays Take into account arrays of opaque types with --auto-map-bindings - Take into account arrays of opaque types when reserving bindings TDefaultIoResolverBase::reserveSlot and getFreeSlot now have a size parameter to reserve a range of bindings. This is used by TDefaultIoResolver::resolveBinding to reserve a continuous range when the type is an array and the target API is GL. - GLSL: Fix #1358: Support "struct name", where name could be a user type - Merge pull request #1402 from greg-lunarg/kg21 Update spirv-tools known-good - Update spirv-tools known-good Includes the following spirv-opt improvements: Preserve inst-to-block and def-use in passes. Add store for var initializer in inlining. Handle types with self references. - Merge pull request #1401 from dneto0/bad-e11 Relax a stringToDouble test for, OSX AppleClang 9.1 - Relax a stringToDouble test for, OSX AppleClang 9.1 1e-323 was flushed to zero. 1e-308 is also flushed to zero. Use 1e-307 instead, which still satisfies the test intent. Fixes #1400 - SPV: Fix #1399 emit ImageGatherExtended when using ConstOffsets operand - Fix #1360: uint->int width conversions must still be typed as uint. - Fix #1395: GLSL volatile maps to SPIR-V Volatile and Coherent. The major version number was bumped in the previous commit to support this. - Change the major revision number for next commit. - Bump revision. - Merge pull request #1397 from LoopDawg/warning-fix-4 Fix several signed/unsigned comparison compile warnings. - Fix several signed/unsigned comparison compile warnings. * Update external/shaderc/shaderc from branch 'master-ndk' to 01c3b1a21e9642a61aa1f6a6a80a4f26b7a964e8 - Merge remote-tracking branch 'aosp/upstream-master' into update-shaderc Includes: 30af9f9 Add virtual dtor to classes with virtual functions a2c044c [kokoro] Update Windows bots. (#468) f7efa14 Update to Glslang generator version 7 Testing: checkbuild.py on Linux; unit tests on Windows Change-Id: I6e6b1c210ed2b7590c695bbb8380127ef5625454 - Add virtual dtor to classes with virtual functions IncluderInterface has virtual functions but does not have a virtual destructor. This class is derived from by FileIncluder w hich overrides those functions. Because there is an interface in use here, it is safe to assume some container is storing IncluderInterface*. If the container instead held FileIncluder* then the virtual functions wouldn't be needed. This causes a problem since FileIncluder has member variables. The destructor of FileIncluder knows to also destruct those member variables (including deallocating their dynamically allocated memory). But when IncluderInterface's destructor is called, it is not virtual and will not call FileIncluder's destructor. So these member variables are never destroyed and their dynamically allocated memory will be leaked. In this case, FileIncluder stores a std::unordered_set<std::string> which will be leaked. This patch adds a virtual destructor to IncluderInterface to make sure FileIncluder's destructor is called and this memory isn't leaked. Use =default and don't redeclare IncluderInterface's dtor - [kokoro] Update Windows bots. (#468) After this change, we should have VS2017 Debug and Release VS2015 Release VS2013 Release - Update to Glslang generator version 7 * Update external/shaderc/spirv-headers from branch 'master-ndk' to 046089ede9682b0d4ffa0638ba11307ae9c2184e - Merge remote-tracking branch 'aosp/upstream-master' into update-shaderc Includes: ff684ff Add enumerants for SPV_KHR_8bit_storage. 02efabd Merge pull request #49 from jdknight/cmake-install-cleanup 8ffa90c Revert "Merge pull request #71 from casey/rebuild-makefile" 443d150 Merge pull request #71 from casey/rebuild-makefile 1fa0d86 Merge pull request #70 from casey/bash-path 87a720a Add missing #include. 96b855e Fix #74: Protect against repeated inclusion of OpenCL.std.h 7de7b23 cmake: support gnu installation directory convention 88ff06a Add a makefile to the top level for convenience d56815b Use /usr/bin/env to avoid hardcoding path to bash d6aeada README.md: update install notes 4ca4743 cmake: support default install target b8d95fb cmake: bump minimum required to support example Testing: checkbuild.py on Linux; unit tests on Windows Change-Id: I71b382df40aaaf35ef51afa1c7de323ba80728de - Add enumerants for SPV_KHR_8bit_storage. - Merge pull request #49 from jdknight/cmake-install-cleanup cmake: support default install target - Revert "Merge pull request #71 from casey/rebuild-makefile" This reverts commit 443d15017aac19a0d5fe3cdce0d8df745475ed51, reversing changes made to 1fa0d86ffb850db90d70b257628cbcf230199bc0. - Merge pull request #71 from casey/rebuild-makefile Add a makefile to the top level for convenience - Merge pull request #70 from casey/bash-path Use /usr/bin/env to avoid hardcoding path to bash - Add missing #include. - Fix #74: Protect against repeated inclusion of OpenCL.std.h - cmake: support gnu installation directory convention Support the handling of the `DESTDIR` environment variable for environments (UNIX-based) opting for an GNU-style installation over a CMake-style installation. Cc: sl1pkn07 <sl1pkn07@gmail.com> Signed-off-by: James Knight <james.d.knight@live.com> - Add a makefile to the top level for convenience - Use /usr/bin/env to avoid hardcoding path to bash - README.md: update install notes Update recommended installation documentation to use the "install" target (from "install-headers"). Signed-off-by: James Knight <james.d.knight@live.com> - cmake: support default install target Allow the common install target to support the installation of header files (rather then having a custom target). Developers should be able to invoke the install target as follows: cmake --build . --target install This commit leaves the original custom target to install headers for interim support. Signed-off-by: James Knight <james.d.knight@live.com> - cmake: bump minimum required to support example The sub-directory "example" takes advantage of the command "target_include_directories", which is only available in CMake v2.8.11+ [1][2]. Bumping the minimum version of CMake required. [1]: https://cmake.org/cmake/help/v2.8.11/cmake.html#command:target_include_directories [2]: https://cmake.org/cmake/help/v2.8.10/cmake.html#section_Commands Signed-off-by: James Knight <james.d.knight@live.com> * Update external/shaderc/spirv-tools from branch 'master-ndk' to b068a2bbb908f16e8e2b7f80f80bfa4a8db10238 - Merge remote-tracking branch 'aosp/upstream-master' into update-shaderc Includes: 85d3715 Update CHANGES 8c7dab5 Fixup line number for OpVectorShuffle ID error. 208921e Fix finding constant with particular type. (#1724) 95b4d47 Fix infinite loop while folding OpVectorShuffle (#1722) 63c1d8f Fix size error when folding vector shuffle. (#1721) 7603944 Remove dead code (#1720) c7da51a Cleanup extraneous namespace qualifies in source/opt. (#1716) e477e75 Remove the module from opt::Function. (#1717) 3ded745 Cleanup CFG header. (#1715) 6803e42 Cleanup some pass code to get context directly. (#1714) a5e4a53 Remove context() method from opt::Function (#1700) 4cc6cd1 Pass the IRContext into the folding rules. (#1709) f96b7f1 use Pass::Run to set the context on each pass. (#1708) 4db9c78 Add option to skip verifying block layout aee809d Update the check-format bot. (#1710) e63551d Add folding rule to merge a vector shuffle feeding another one. 4470ff4 Update CHANGES 2c6185e Enforce block layout rules even when relaxed c02d216 Update docs to reflect new bot status. e70a412 Move validation files to val/ directory (#1692) 2cce2c5 Move tests into namespaces (#1689) 7d6c90c Reopen stdin for binary as needed fec6315 Vulkan permits non-monotonic offsets for block members eb48263 Description for Android build ead54bb Use spv_result_t instead of bool 6e550f4 Disable Travis bots, and Appveyor Release bots. cbdbbe9 Fix up code to make ClangTidy happy. 84846b7 Cleanup whitespace lint warnings. (#1690) 9532aed Fix unused param errors when Effcee not present a3e3869 Convert validation to use libspriv::Instruction where possible. (#1663) 43144e3 Move the validation code into the val:: namespace (#1682) 48326d4 Move link/ code to anonymous namespace (#1679) e6b9533 Move the ir namespace to opt. (#1680) 50312ca Start SPIRV-Tools v2018.5-dev f508896 Finalize SPIRV-Tools v2018.4 9de00c9 Update CHANGES 3dad1cd Change libspirv to spvtools namespace (#1678) 76e0bde Move utils/ to spvtools::utils 9836b05 Move comp code into comp namespace 5e0276b validator: use RowMajor, ArrayStride, MatrixStride 1a283f4 Layout validation: Permit {vec3; float} tight packing 9795137 Enable Kokoro buildbots. (#1625) c460f44 Add a check for invalid exits from case construct. fa78d3b Update SPIRV-Headers a069499 Fix layout checks for StorageBuffer and PushConstant storage classes a45d4ca Move folding routines into a class 9ecbcf5 Make sure the constant folder get the correct type. 101a9bc Add private to local to optimization and size passes. 4926f29 Let symbol export tests respect SPIRV_SKIP_TESTS 30a9cef Support SPV_KHR_8bit_storage 5109104 Produce better error diagnostics in the CFG validation. (#1660) 465f281 Revert change and stop running remove duplicates. 2eb9bfb Remove stores of undef. b67beca GLSL.std.450 Refract Eta can be any float scalar 7cc9f36 Add test for CFG alteration by compact IDs 4717d24 Fix assert during compact IDs pass (#1649) 878b3b4 check_symbol_exports on Python3, Mac f393b0e Don't merge types of resources c2e3e67 validator: Fix storage buffer layout message 8ecd833 Block-decorated structs must list members in offset-order 2992340 Add validation for structs decorated as Block or BufferBlock. 0d43e10 Use type id when looking up vector type 4d99fcb Validator test: artificially lower limit on local var limit 1854064 Setup gclient and presubmit file. ba602c9 Add a WIP WebGPU environment. It disallows OpUndef e7ace1b Add Vulkan 1.1 capability sets 8d65c89 Instruction lookup succeeds if it's enabled by a capability f80696e [val] Add extra context to error messages. (#1600) 356193e Reland "Disallow array-of-arrays with DescriptorSets when validating. (#1586)" (#1621) c4304ea Reland "Disallow array-of-arrays with DescriptorSets when validating. (#1586)" d3ed998 Validate Ids before DataRules. (#1622) ea7239f Structured switch checks 4f866ab Validate static uses of interfaces b49cbf0 Fix buffer read overrun in linker 1f7b1f1 Small vector optimization for operands. 700ebd3 Make fewer test executables 363bfca Operand lookup succeeds if it's enabled by a capability 06de868 Check for invalid branches into construct body. 035afb8 Update CHANGES 63c9bba [val] Output id names along with numbers in validate_id (#1601) f2c93c6 Revert "Disallow array-of-arrays with DescriptorSets when validating. (#1586)" (#1607) e3f1f3b Disallow array-of-arrays with DescriptorSets when validating. (#1586) a1f9e13 Preserve inst-to-block and def-use in passes. Testing: checkbuild.py on Linux; unit tests on Windows Change-Id: I03fced3c0ef41119090d301e3393acd73b3090da - Update CHANGES - Fixup line number for OpVectorShuffle ID error. This CL updates the code to pull a valid instruction for the line number when outputting a component error in OpVectorShuffle. The error line isn't the best at this point as it points at the component, but it's better then a -1 (turning to max<size_t>) that was being output. The error messages has been updated to better reflect what the error is attempting to say. Issue 1719. - Fix finding constant with particular type. (#1724) With current implementation, the constant manager does not keep around two constant with the same value but different types when the types hash to the same value. So when you start looking for that constant you will get a constant with the wrong type back. I've made a few changes to the constant manager to fix this. First off, I have changed the map from constant to ids to be an std::multimap. This way a single constant can be mapped to mutiple ids each representing a different type. Then when asking for an id of a constant, we can search all of the ids associated with that constant in order to find the one with the correct type. - Fix infinite loop while folding OpVectorShuffle (#1722) When folding an OpVectorShuffle where the first operand is defined by an OpVectorShuffle, is unused, and is equal to the second, we end up with an infinite loop. This is because we think we change the instruction, but it does not actually change. So we keep trying to folding the same instruction. This commit fixes up that specific issue. When the operand is unused, we replace it with Null. - Fix size error when folding vector shuffle. (#1721) When folding a vector shuffle that feeds another vector shuffle causes the size of the first operand to change, when other indices have to be adjusted reletive to the new size. - Remove dead code (#1720) Remove commented out code from validate_id. - Cleanup extraneous namespace qualifies in source/opt. (#1716) This CL follows up on the opt namespacing CLs by removing the unnecessary opt:: and opt::analysis:: namespace prefixes. - Remove the module from opt::Function. (#1717) The function class provides a {Set|Get}Parent call in order to provide the context to the LoopDescriptor methods. This CL removes the module from Function and provides the needed context directly to LoopDescriptor on creation. - Cleanup CFG header. (#1715) This CL removes some unused methods from CFG, makes the constructor explicit and moves the using statement to the cpp file where it's used. - Cleanup some pass code to get context directly. (#1714) Instead of going through the instruction we can access the context() directly from the pass. Issue #1703 - Remove context() method from opt::Function (#1700) This CL removes the context() method from opt::Function. In the places where the context() was used we can retrieve, or provide, the context in another fashion. - Pass the IRContext into the folding rules. (#1709) This CL updates the folding rules to receive the IRContext as a paramter instead of retrieving off of the Instruction. Issue #1703 - use Pass::Run to set the context on each pass. (#1708) Currently the IRContext is passed into the Pass::Process method. It is then up to the individual pass to store the context into the context_ variable. This CL changes the Run method to store the context before calling Process which no-longer receives the context as a parameter. - Add option to skip verifying block layout We need this to avoid emitting errors on DirectX layout rules. - Update the check-format bot. (#1710) - Add folding rule to merge a vector shuffle feeding another one. - Update CHANGES - Enforce block layout rules even when relaxed - Vulkan 1.0 uses strict layout rules - Vulkan 1.0 with relaxed-block-layout validator option enforces all rules except for the relaxation of vector offset. - Vulkan 1.1 and later always supports relaxed block layout Add spot check tests for the relaxed-block-layout scenarios. Fixes #1697 - Update docs to reflect new bot status. - Move validation files to val/ directory (#1692) This CL moves the various validate files into the val/ directory with the rest of the validation infrastructure. This matches how opt/ is setup with the passes with the infrastructure. - Move tests into namespaces (#1689) This CL moves the test into namespaces based on their directories. - Reopen stdin for binary as needed Fixes #1688 - Vulkan permits non-monotonic offsets for block members Other environments do not. Add tests for OpenGL 4.5 and SPIR-V universal 1.0 to ensure they still check monotonic layout. For universal 1.0, we're assuming it otherwise follows Vulkan rules for block layout. Fixes #1685 - Description for Android build - Use spv_result_t instead of bool Using bool is confusing here, and results in an MSVC warning about an implicit cast to bool. - Disable Travis bots, and Appveyor Release bots. Kokoro bots currently cover all Travis bots: macos-clang-debug macos-clang-release ubuntu-clang-debug ubuntu-clang-release ubuntu-gcc-debug ubuntu-gcc-release ndk-build android check-format Kokoro bots also cover all Windows Release builds: windows-VS2013-release windows-VS2015-release windows-VS2017-release Due to a compiler issue on the Kokoro Windows VM, we currently do not run the Debug build on Kokoro. Therefore, I am disabling all Travis jobs and the appveyor Release jobs. - Fix up code to make ClangTidy happy. Just a few changes to pass `std::function` objects by const reference instead of by value. - Cleanup whitespace lint warnings. (#1690) This CL cleans up the whitespace warnings and enables the check when running 'git cl presubmit --all -uf'. - Fix unused param errors when Effcee not present - Convert validation to use libspriv::Instruction where possible. (#1663) For the instructions which execute after the IdPass check we can provide the Instruction instead of the spv_parsed_instruction_t. This Instruction class provides a bit more context (like the source line) that is not available from spv_parsed_instruction_t. - Move the validation code into the val:: namespace (#1682) This CL moves the validation code to the val:: namespace. This makes it clearer which instance of the Instruction and other classes are being referred too. - Move link/ code to anonymous namespace (#1679) Most of the link code is marked as static. This CL introduces an anonymous namespace and removes the static methods. The last two methods are exposed in the public API and have been left in the spvtools namespace. - Move the ir namespace to opt. (#1680) This CL moves the files in opt/ to consistenly be under the opt:: namespace. This frees up the ir:: namespace so it can be used to make a shared ir represenation. - Start SPIRV-Tools v2018.5-dev - Finalize SPIRV-Tools v2018.4 - Update CHANGES - Change libspirv to spvtools namespace (#1678) This CL changes all of the libspirv namespace code to spvtools to match the rest of the code base. - Move utils/ to spvtools::utils Currently the utils/ folder uses both spvutils:: and spvtools::utils. This CL changes the namespace to consistenly be spvtools::utils to match the rest of the codebase. - Move comp code into comp namespace This CL moves the code in the comp/ directories into the comp namespace. - validator: use RowMajor, ArrayStride, MatrixStride Implement rules for row-major matrices Use ArrayStride and MatrixStride to compute sizes Propagate matrix stride and RowMajor/ColumnMajor through array members of structs. Fixes #1637 Fixes #1668 - Layout validation: Permit {vec3; float} tight packing Fixes KhronosGroup/SPIRV-Tools#1666 - Enable Kokoro buildbots. (#1625) - Add a check for invalid exits from case construct. Fixes #1618. Adds a check that validates acceptable exits from case constructs. Case constructs may only exit to another case construct, the corresponding merge, an outer loop continue or outer loop merge. - Update SPIRV-Headers - Fix layout checks for StorageBuffer and PushConstant storage classes Fixes #1664 : PushConstant with Block follows storage buffer rules PushConstant variables were being checked with block rules, which are too strict. Fixes #1606 : StorageBuffer with Block layout follows buffer rules StorageBuffer variables were not being checked before. Fix layout messages: say storage class and decoration We need to provide more information about storage class and decoration. - Move folding routines into a class The folding routines are currently global functions. They also rely on data in an std::map that holds the folding rules for each opcode. This causes that map to not have a clear owner, and therefore never gets deleted. There has been a request to delete this map. To implement this, we will create a InstructionFolder class that owns the maps. The IRContext will own the InstructionFolder instance. Then the global functions will become public memeber functions of the InstructionFolder. Fixes KhronosGroup/SPIRV-Tools#1659. - Make sure the constant folder get the correct type. There are a few locations where we need to handle duplicate types. We cannot merge them because they may be needed for reflection. When this happens we need do some extra lookups in the type manager. The specific fixes are: 1) When generating a constant through `GetDefiningInstruction` accept and use an id for the desired type of the constant. This will make sure you get the type that is needed. 2) In Private-to-local, make sure we to update the def-use chains when a new pointer type is created. 3) In the type manager, make sure that `FindPointerToType` returns a pointer that points to the given type and not a duplicate type. 4) In scalar replacment, make sure the null constants that are created are the correct type. - Add private to local to optimization and size passes. Many optimization will run on function scope symbols only. When symbols are moved from private scope to function scople, then these optimizations can do more. I believe it is a good idea to run this pass with both -O and -Os. To get the most out of it it should be run ASAP after inlining and something that remove all of the dead functions. - Let symbol export tests respect SPIRV_SKIP_TESTS - Support SPV_KHR_8bit_storage - Add asm/dis test for SPV_KHR_8bit_storage - validator: SPV_KHR_8bit_storage capabilities enable declaration of 8bit int TODO: - validator: ban arithmetic on 8bit unless Int8 is enabled Covered by KhronosGroup/SPIRV-Tools#1595 - Produce better error diagnostics in the CFG validation. (#1660) Produce better error diagnostics in the CFG validation. This CL fixes up several issues with the diagnostic error line output in the CFG validation code. For the cases where we can determine a better line it has been output. For other cases, we removed the diagnostic line and the error line number from the results. Fixes #1657 - Revert change and stop running remove duplicates. Revert "Don't merge types of resources" This reverts commit f393b0e48014867eaada2044841cd7e0140b3d0d, but leaves the tests that were added. Added new test. These test are the so that, if someone tries the same change I made, they will see the test that they need to handle. Don't run remove duplicates in -O and -Os Romve duplicates was run to help reduce compile time when looking for types in the type manager. I've run compile time test on three sets of shaders, and the compile time does not seem to change. It should be safe to remove it. - Remove stores of undef. When storing an undef, any value is valid, including the one already in that memory location. So we can avoid the store. - GLSL.std.450 Refract Eta can be any float scalar This is a decision from Khronos-internal SPIR-V spec issue 337. - Add test for CFG alteration by compact IDs The Compact IDs pass can corrupt the CFG, but first the CFG has to be setup. To do this, a test that builds the CFG, then performs the compact IDs pass, then checks context consistency. Fixes KhronosGroup/SPIRV-Tools#1648 - Fix assert during compact IDs pass (#1649) During the compact IDs optimization pass, the result IDs of some basic blocks can change. In spite of this, GetPreservedAnalyses indicated that the CFG was preserved. But the CFG relies on the basic blocks having the same IDs. Simply removing this flag resolves the issue by preventing the CFG check. Also Removes combinators and namemap preserved analyses from compact IDs pass. - check_symbol_exports on Python3, Mac subprocess.Popen returns byte data by default. Python2 was happy to try to execute string operations on such data and hope for the best, but python3 is more persnickety. Luckily, there's a simple way to indicate to the Popen class that text data is wanted that benefits the script. Just specifying universal_newlines will cause the returned data to be text and also convert any system-specific newlines to '\n' which the script relies on anyway. Enabled on Mac as an incidental change after confirming that the script works there just as well as it does on Linux. It probably works on FreeBSD too, but I retired my BSD system years ago. So I have no way to check. Don't run it on Windows. - It didn't work after all. It was just detecting non-posix and returning success. - Don't merge types of resources When doing reflection users care about the names of the variable, the name of the type, and the name of the members. Remove duplicates breaks this because it removes the names one of the types when merging. To fix this we have to keep the different types around for each resource. This commit adds code to remove duplicates to look for the types uses to describe resources, and make sure they do not get merged. However, allow merging of a type used in a resource with something not used in a resource. Was done when the non resource type came second. This could have a negative effect on compile time, but it was not expected to be much. Fixes KhronosGroup/SPIRV-Tools#1372. - validator: Fix storage buffer layout message - Block-decorated structs must list members in offset-order Additionally, implmentes code review feedback. Adds more detailed messages for Block and BufferBlock layout errors. Fixes #1638 - Add validation for structs decorated as Block or BufferBlock. Fixes #937 Stop std140/430 validation when runtime array is encountered. Check for standard uniform/storage buffer layout instead of std140/430. Added validator command line switch to skip block layout checking. Validate structs decorated as Block/BufferBlock only when they are used as variable with storage class of uniform or push constant. Expose --relax-block-layout to command line. dneto0 modification: - Use integer arithmetic instead of floor. - Use type id when looking up vector type Fixes #1634 * Vector components of composite constructs used wrong accessor - Validator test: artificially lower limit on local var limit We need this to reduce the test time on Visual Studio debug builds. AppVeyor times out at 300s for a process. Artificially lower the local variable limit check for testing purposes. We don't get much value from using the full 500K+ variables. Use a limit of 5000 instead. Fixes KhronosGroup/SPIRV-Tools#1632 - Setup gclient and presubmit file. This CL adds the necessary files to use gclient and the depot_tools with the SPIRV-Tools directory. This allows doing things like `git cl format` to format code pre-upload and `git cl presubmit -uf` to run presubmit checks over the code. The dependencies are all added to the DEPS file and will be auto-downloaded. They are all pin'd to specific revisions so everyone has the same checkout. Clang is included in the checkout so it will be consistent over usages. Use clang-format - Add a WIP WebGPU environment. It disallows OpUndef Add SPV_ENV_WEBGPU_0 for work-in-progress WebGPU. val: Disallow OpUndef in WebGPU env Silence unused variable warnings when !defined(SPIRV_EFFCE) Limit visibility of validate_instruction.cpp's symbols Only InstructionPass needs to be visible so all other functions are put in an anonymous namespace inside the libspirv namespace. - Add Vulkan 1.1 capability sets Fixes #1597 * Classifies useable capabilities for Vulkan 1.1 * Updates tests - Instruction lookup succeeds if it's enabled by a capability Also add a corresponding check for capabilities in the validator. Update previously existing test cases where an instruction used to fail assembling because of a version check, but now they succeed because the instruction is also guarded by a capability. Now it should assemble. Add tests to ensure that capabilities are checked appropriately. The explicitly reserved instructions OpImageSparseSampleProj* now assemble, but they fail validation. Fixes #1624 - [val] Add extra context to error messages. (#1600) [val] Add extra context to error messages. This CL extends the error messages produced by the validator to output the disassembly of the errored line. The validation_id messages have also been updated to print the line number of the error instead of the word number. Note, the error number is from the start of the SPIR-V, it does not include any headers printed in the disassembled code. Fixes #670, #1581 - Reland "Disallow array-of-arrays with DescriptorSets when validating. (#1586)" (#1621) This CL reverts the revert of 'Disallow array-of-arrays with DescriptorSets when validating." Other changes have been committed which should aleviate the AppVeryor resource constraints. This reverts commit f2c93c6e124836797311facb8449f9a0b76fefc2. This CL adds validation to disallow using an array-of-arrays when attached to a DescriptorSet. Fixes #1522 - Reland "Disallow array-of-arrays with DescriptorSets when validating. (#1586)" This CL reverts the revert of 'Disallow array-of-arrays with DescriptorSets when validating." Other changes have been committed which should aleviate the AppVeryor resource constraints. This reverts commit f2c93c6e124836797311facb8449f9a0b76fefc2. This CL adds validation to disallow using an array-of-arrays when attached to a DescriptorSet. Fixes #1522 - Validate Ids before DataRules. (#1622) Validate Ids before DataRules. The DataRule validators call FindDefs with the assumption that they definitions being looked at can be found. This may not be true if we have not validated identifiers first. This CL flips the IdPass and DataRulesPass to fix this issue. - Structured switch checks Fixes #491 * Basic blocks now have a link to the terminator * Check all case sepecific rules * Missing check for branching into the middle of a case (#1618) - Validate static uses of interfaces Fixes #1120 Checks that all static uses of the Input and Output variables are listed as interfaces in each corresponding entry point declaration. * Changed validation state to track interface lists * updated many tests * Modified validation state to store entry point names * Combined with interface list and called EntryPointDescription * Updated uses * Changed interface validation error messages to output entry point name in addtion to ID - Fix buffer read overrun in linker Fixes an ASAN failure. Was occuring when generating the OpModuleProcessed instruction declaring that this module was processed by the linker. - Small vector optimization for operands. We replace the std::vector in the Operand class by a new class that does a small size optimization. This helps improve compile time on Windows. Tested on three sets of shaders. Trying various values for the small vector. The optimal value for the operand class was 2. However, for the Instruction class, using an std::vector was optimal. Size of "0" means that an std::vector was used. Instruction size 0 4 8 Operand Size 0 489 544 684 1 593 487 2 469 570 4 473 8 505 This is a single thread run of ~120 shaders. For the multithreaded run the results were the similar. The basline time was ~62sec. The optimal configuration was an 2 for the OperandData and an std::vector for the OperandList with a compile time of ~38sec. Similar expiriments were done with other sets of shaders. The compile time still improved, but not as much. Contributes to KhronosGroup/SPIRV-Tools#1609. - Make fewer test executables Try to reduce the amount of disk space used by especially by debug builds, which may be contributing to AppVeyor failures. Collapses tests in categories: - validator - loop optimizations - dominator analysis - linker Contributes to #1615 - Operand lookup succeeds if it's enabled by a capability - Fix tests for basic group operations (e.g. Reduce) to allow for new capabilities in SPIR-V 1.3 that enable them. - Refactor operand capability check to avoid code duplication and to put all checks that don't need table lookup before any table lookup. - Test round trip assembly/disassembly support for extension SPV_NV_viewport_array2 - Test assembly and validation of decoration ViewportRelativeNV Fixes #1596 - Check for invalid branches into construct body. Fixes #1281 * New structured cfg check: all non-construct header blocks' predecessors must come from within the construct * New function to calculate blocks in a construct * Fixed a bug in BasicBlock type bitset Relaxing check to not consider unreachable predecessors * Fixing broken common uniform elim test - Update CHANGES - [val] Output id names along with numbers in validate_id (#1601) This CL updates the validate_id code to output the name of the object along with the id number. There were a few instances which already output the name, this just extends to all of them. Now, the output should say 123[obj] instead of just 123. Issue #1581 - Revert "Disallow array-of-arrays with DescriptorSets when validating. (#1586)" (#1607) This reverts commit e3f1f3bda51387626094b054a19973c3d25b62dc. - Disallow array-of-arrays with DescriptorSets when validating. (#1586) * Disallow array-of-arrays with DescriptorSets when validating. This CL adds validation to disallow using an array-of-arrays when attached to a DescriptorSet. Fixes #1522 - Preserve inst-to-block and def-use in passes. The following passes are updated to preserve the inst-to-block and def-use analysies: private-to-local aggressive dead-code elimination dead branch elimination local-single-block elimination local-single-store elimination reduce load size compact ids (inst-to-block only) merge block dead-insert elimination ccp The one execption is that compact ids still kills the def-use manager. This is because it changes so many ids it is faster to kill and rebuild. Does everything in KhronosGroup/SPIRV-Tools#1593 except for the changes to merge return.
I have run into a problem with spirv-opt since the release of Vulkan SDK 1.0.68.0. The remove-duplicates pass seems to be clobbering my shader. Prior to that release, things were fine. This may well be something that I am doing wrong, but I have been unable to determine what thus far.
spirv-opt from Vulkan SDK 1.0.68.0 self-identifies as:
The original SPIR-V is constructed by glslangValidator from the same SDK.
Some relevant bits from my shader:
Before any optimisation the disassembly shows the following section:
After running just the remove-duplicates pass this has changed to:
There are other changes, but off the bat this seems odd.
Running the optimiser with every -O pass except for remove-duplicates generates SPIR-V that appears to work fine.
I tried using spirv-opt from the CI build from commit 6cd6e5e, but with no change in behaviour.
The following is a cut-down that generates the odd difference when running just remove-duplicates:
To demonstrate the difference:
The text was updated successfully, but these errors were encountered: