Giter Club home page Giter Club logo

spirv-tools's Introduction

SPIR-V Tools

OpenSSF Scorecard

NEWS 2023-01-11: Development occurs on the main branch.

Overview

The SPIR-V Tools project provides an API and commands for processing SPIR-V modules.

The project includes an assembler, binary module parser, disassembler, validator, and optimizer for SPIR-V. Except for the optimizer, all are based on a common static library. The library contains all of the implementation details, and is used in the standalone tools whilst also enabling integration into other code bases directly. The optimizer implementation resides in its own library, which depends on the core library.

The interfaces have stabilized: We don't anticipate making a breaking change for existing features.

SPIR-V is defined by the Khronos Group Inc. See the SPIR-V Registry for the SPIR-V specification, headers, and XML registry.

Downloads

The official releases for SPIRV-Tools can be found on LunarG's SDK download page.

For convenience, here are also links to the latest builds (HEAD). Those are untested automated builds. Those are not official releases, nor are guaranteed to work. Official releases builds are in the Vulkan SDK.

LinuxLinux Build Status MacOSMacOS Build Status WindowsWindows Build Status

More downloads

Versioning SPIRV-Tools

See CHANGES for a high level summary of recent changes, by version.

SPIRV-Tools project version numbers are of the form vyear.index and with an optional -dev suffix to indicate work in progress. For example, the following versions are ordered from oldest to newest:

  • v2016.0
  • v2016.1-dev
  • v2016.1
  • v2016.2-dev
  • v2016.2

Use the --version option on each command line tool to see the software version. An API call reports the software version as a C-style string.

Releases

The official releases for SPIRV-Tools can be found on LunarG's SDK download page.

You can find either the prebuilt, and QA tested binaries, or download the SDK Config, which lists the commits to use to build the release from scratch.

GitHub releases are deprecated, and we will not publish new releases until further notice.

Supported features

Assembler, binary parser, and disassembler

  • Support for SPIR-V 1.0, through 1.5
    • Based on SPIR-V syntax described by JSON grammar files in the SPIRV-Headers repository.
    • Usually, support for a new version of SPIR-V is ready within days after publication.
  • Support for extended instruction sets:
    • GLSL std450 version 1.0 Rev 3
    • OpenCL version 1.0 Rev 2
  • Assembler only does basic syntax checking. No cross validation of IDs or types is performed, except to check literal arguments to OpConstant, OpSpecConstant, and OpSwitch.

See docs/syntax.md for the assembly language syntax.

Validator

The validator checks validation rules described by the SPIR-V specification.

Khronos recommends that tools that create or transform SPIR-V modules use the validator to ensure their outputs are valid, and that tools that consume SPIR-V modules optionally use the validator to protect themselves from bad inputs. This is especially encouraged for debug and development scenarios.

The validator has one-sided error: it will only return an error when it has implemented a rule check and the module violates that rule.

The validator is incomplete. See the CHANGES file for reports on completed work, and the Validator sub-project for planned and in-progress work.

Note: The validator checks some Universal Limits, from section 2.17 of the SPIR-V spec. The validator will fail on a module that exceeds those minimum upper bound limits. The validator has been parameterized to allow larger values, for use when targeting a more-than-minimally-capable SPIR-V consumer.

See tools/val/val.cpp or run spirv-val --help for the command-line help.

Optimizer

The optimizer is a collection of code transforms, or "passes". Transforms are written for a diverse set of reasons:

  • To restructure, simplify, or normalize the code for further processing.
  • To eliminate undesirable code.
  • To improve code quality in some metric such as size or performance. Note: These transforms are not guaranteed to actually improve any given metric. Users should always measure results for their own situation.

As of this writing, there are 67 transforms including examples such as:

  • Simplification
    • Strip debug info
    • Strip reflection info
  • Specialization Constants
    • Set spec constant default value
    • Freeze spec constant to default value
    • Fold OpSpecConstantOp and OpSpecConstantComposite
    • Unify constants
    • Eliminate dead constant
  • Code Reduction
    • Inline all function calls exhaustively
    • Convert local access chains to inserts/extracts
    • Eliminate local load/store in single block
    • Eliminate local load/store with single store
    • Eliminate local load/store with multiple stores
    • Eliminate local extract from insert
    • Eliminate dead instructions (aggressive)
    • Eliminate dead branches
    • Merge single successor / single predecessor block pairs
    • Eliminate common uniform loads
    • Remove duplicates: Capabilities, extended instruction imports, types, and decorations.
  • Normalization
    • Compact IDs
    • CFG cleanup
    • Flatten decorations
    • Merge returns
    • Convert AMD-specific instructions to KHR instructions
  • Code improvement
    • Conditional constant propagation
    • If-conversion
    • Loop fission
    • Loop fusion
    • Loop-invariant code motion
    • Loop unroll
  • Other
    • Graphics robust access
    • Upgrade memory model to VulkanKHR

Additionally, certain sets of transformations have been packaged into higher-level recipes. These include:

  • Optimization for size (spirv-opt -Os)
  • Optimization for performance (spirv-opt -O)

For the latest list with detailed documentation, please refer to include/spirv-tools/optimizer.hpp.

For suggestions on using the code reduction options, please refer to this white paper.

Linker

Note: The linker is still under development.

Current features:

  • Combine multiple SPIR-V binary modules together.
  • Combine into a library (exports are retained) or an executable (no symbols are exported).

See the CHANGES file for reports on completed work, and the General sub-project for planned and in-progress work.

Reducer

Note: The reducer is still under development.

The reducer simplifies and shrinks a SPIR-V module with respect to a user-supplied interestingness function. For example, given a large SPIR-V module that cause some SPIR-V compiler to fail with a given fatal error message, the reducer could be used to look for a smaller version of the module that causes the compiler to fail with the same fatal error message.

To suggest an additional capability for the reducer, file an issue with "Reducer:" as the start of its title.

Fuzzer

Note: The fuzzer is still under development.

The fuzzer applies semantics-preserving transformations to a SPIR-V binary module, to produce an equivalent module. The original and transformed modules should produce essentially identical results when executed on identical inputs: their results should differ only due to floating-point round-off, if at all. Significant differences in results can pinpoint bugs in tools that process SPIR-V binaries, such as miscompilations. This metamorphic testing approach is similar to the method used by the GraphicsFuzz project for fuzzing of GLSL shaders.

To suggest an additional capability for the fuzzer, file an issue with "Fuzzer:" as the start of its title.

Diff

Note: The diff tool is still under development.

The diff tool takes two SPIR-V files, either in binary or text format and produces a diff-style comparison between the two. The instructions between the src and dst modules are matched as best as the tool can, and output is produced (in src id-space) that shows which instructions are removed in src, added in dst or modified between them. The order of instructions are not retained.

Matching instructions between two SPIR-V modules is not trivial, and thus a number of heuristics are applied in this tool. In particular, without debug information, match functions is nontrivial as they can be reordered. As such, this tool is primarily useful to produce the diff of two SPIR-V modules derived from the same source, for example before and after a modification to the shader, before and after a transformation, or SPIR-V produced from different tools.

Extras

  • Utility filters
  • Build target spirv-tools-vimsyntax generates file spvasm.vim. Copy that file into your $HOME/.vim/syntax directory to get SPIR-V assembly syntax highlighting in Vim. This build target is not built by default.

Contributing

The SPIR-V Tools project is maintained by members of the The Khronos Group Inc., and is hosted at https://github.com/KhronosGroup/SPIRV-Tools.

Consider joining the [email protected] mailing list, via https://www.khronos.org/spir/spirv-tools-mailing-list/. The mailing list is used to discuss development plans for the SPIRV-Tools as an open source project. Once discussion is resolved, specific work is tracked via issues and sometimes in one of the projects.

(To provide feedback on the SPIR-V specification, file an issue on the SPIRV-Headers GitHub repository.)

See docs/projects.md to see how we use the GitHub Project feature to organize planned and in-progress work.

Contributions via merge request are welcome. Changes should:

We intend to maintain a linear history on the GitHub main branch.

Getting the source

Example of getting sources, assuming SPIRV-Tools is configured as a standalone project:

git clone https://github.com/KhronosGroup/SPIRV-Tools.git   spirv-tools
cd spirv-tools

# Check out sources for dependencies, at versions known to work together,
# as listed in the DEPS file.
python3 utils/git-sync-deps

For some kinds of development, you may need the latest sources from the third-party projects:

git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-tools/external/spirv-headers
git clone https://github.com/google/googletest.git          spirv-tools/external/googletest
git clone https://github.com/google/effcee.git              spirv-tools/external/effcee
git clone https://github.com/google/re2.git                 spirv-tools/external/re2
git clone https://github.com/abseil/abseil-cpp.git          spirv-tools/external/abseil_cpp

Dependency on Effcee

Some tests depend on the Effcee library for stateful matching. Effcee itself depends on RE2, and RE2 depends on Abseil.

  • If SPIRV-Tools is configured as part of a larger project that already uses Effcee, then that project should include Effcee before SPIRV-Tools.
  • Otherwise, SPIRV-Tools expects Effcee sources to appear in external/effcee, RE2 sources to appear in external/re2, and Abseil sources to appear in external/abseil_cpp.

Source code organization

  • example: demo code of using SPIRV-Tools APIs
  • external/googletest: Intended location for the googletest sources, not provided
  • external/effcee: Location of Effcee sources, if the effcee library is not already configured by an enclosing project.
  • external/re2: Location of RE2 sources, if the re2 library is not already configured by an enclosing project. (The Effcee project already requires RE2.)
  • external/abseil_cpp: Location of Abseil sources, if Abseil is not already configured by an enclosing project. (The RE2 project already requires Abseil.)
  • include/: API clients should add this directory to the include search path
  • external/spirv-headers: Intended location for SPIR-V headers, not provided
  • include/spirv-tools/libspirv.h: C API public interface
  • source/: API implementation
  • test/: Tests, using the googletest framework
  • tools/: Command line executables

Tests

The project contains a number of tests, used to drive development and ensure correctness. The tests are written using the googletest framework. The googletest source is not provided with this project. There are two ways to enable tests:

  • If SPIR-V Tools is configured as part of an enclosing project, then the enclosing project should configure googletest before configuring SPIR-V Tools.
  • If SPIR-V Tools is configured as a standalone project, then download the googletest source into the <spirv-dir>/external/googletest directory before configuring and building the project.

Build

Note: Prebuilt binaries are available from the downloads page.

First get the sources. Then build using CMake, Bazel, Android ndk-build, or the Emscripten SDK.

Build using CMake

You can build the project using CMake:

cd <spirv-dir>
mkdir build && cd build
cmake [-G <platform-generator>] <spirv-dir>

Once the build files have been generated, build using the appropriate build command (e.g. ninja, make, msbuild, etc.; this depends on the platform generator used above), or use your IDE, or use CMake to run the appropriate build command for you:

cmake --build . [--config Debug]  # runs `make` or `ninja` or `msbuild` etc.

Note about the fuzzer

The SPIR-V fuzzer, spirv-fuzz, can only be built via CMake, and is disabled by default. To build it, clone protobuf and use the SPIRV_BUILD_FUZZER CMake option, like so:

# In <spirv-dir> (the SPIRV-Tools repo root):
git clone --depth=1 --branch v3.13.0.1 https://github.com/protocolbuffers/protobuf external/protobuf

# In your build directory:
cmake [-G <platform-generator>] <spirv-dir> -DSPIRV_BUILD_FUZZER=ON
cmake --build . --config Debug

You can also add -DSPIRV_ENABLE_LONG_FUZZER_TESTS=ON to build additional fuzzer tests.

Build using Bazel

You can also use Bazel to build the project.

bazel build :all

Build a node.js package using Emscripten

The SPIRV-Tools core library can be built to a WebAssembly node.js module. The resulting SpirvTools WebAssembly module only exports methods to assemble and disassemble SPIR-V modules.

First, make sure you have the Emscripten SDK. Then:

cd <spirv-dir>
./source/wasm/build.sh

The resulting node package, with JavaScript and TypeScript bindings, is written to <spirv-dir>/out/web.

Note: This builds the package locally. It does not publish it to npm.

To test the result:

node ./test/wasm/test.js

Tools you'll need

For building and testing SPIRV-Tools, the following tools should be installed regardless of your OS:

  • CMake: if using CMake for generating compilation targets, you need to install CMake Version 2.8.12 or later.
  • Python 3: for utility scripts and running the test suite.
  • Bazel (optional): if building the source with Bazel, you need to install Bazel Version 7.0.2 on your machine. Other versions may also work, but are not verified.
  • Emscripten SDK (optional): if building the WebAssembly module.

SPIRV-Tools is regularly tested with the following compilers:

On Linux

  • GCC version 9.3
  • Clang version 10.0

On MacOS

  • AppleClang 11.0

On Windows

  • Visual Studio 2017
  • Visual Studio 2019
  • Visual Studio 2022

Note: Visual Studio 2017 has incomplete c++17 support. We might stop testing it soon. Other compilers or later versions may work, but they are not tested.

CMake options

The following CMake options are supported:

  • SPIRV_BUILD_FUZZER={ON|OFF}, default OFF - Build the spirv-fuzz tool.
  • SPIRV_COLOR_TERMINAL={ON|OFF}, default ON - Enables color console output.
  • SPIRV_SKIP_TESTS={ON|OFF}, default OFF- Build only the library and the command line tools. This will prevent the tests from being built.
  • SPIRV_SKIP_EXECUTABLES={ON|OFF}, default OFF- Build only the library, not the command line tools and tests.
  • SPIRV_USE_SANITIZER=<sanitizer>, default is no sanitizing - On UNIX platforms with an appropriate version of clang this option enables the use of the sanitizers documented here. This should only be used with a debug build.
  • SPIRV_WARN_EVERYTHING={ON|OFF}, default OFF - On UNIX platforms enable more strict warnings. The code might not compile with this option enabled. For Clang, enables -Weverything. For GCC, enables -Wpedantic. See CMakeLists.txt for details.
  • SPIRV_WERROR={ON|OFF}, default ON - Forces a compilation error on any warnings encountered by enabling the compiler-specific compiler front-end option. No compiler front-end options are enabled when this option is OFF.

Additionally, you can pass additional C preprocessor definitions to SPIRV-Tools via setting SPIRV_TOOLS_EXTRA_DEFINITIONS. For example, by setting it to /D_ITERATOR_DEBUG_LEVEL=0 on Windows, you can disable checked iterators and iterator debugging.

Android ndk-build

SPIR-V Tools supports building static libraries libSPIRV-Tools.a and libSPIRV-Tools-opt.a for Android. Using the Android NDK r25c or later:

cd <spirv-dir>

export ANDROID_NDK=/path/to/your/ndk   # NDK r25c or later

mkdir build && cd build
mkdir libs
mkdir app

$ANDROID_NDK/ndk-build -C ../android_test     \
                      NDK_PROJECT_PATH=.      \
                      NDK_LIBS_OUT=`pwd`/libs \
                      NDK_APP_OUT=`pwd`/app

Updating DEPS

Occasionally the entries in DEPS will need to be updated. This is done on demand when there is a request to do this, often due to downstream breakages. To update DEPS, run utils/roll_deps.sh and confirm that tests pass. The script requires Chromium's depot_tools.

Library

Usage

The internals of the library use C++17 features, and are exposed via both a C and C++ API.

In order to use the library from an application, the include path should point to <spirv-dir>/include, which will enable the application to include the header <spirv-dir>/include/spirv-tools/libspirv.h{|pp} then linking against the static library in <spirv-build-dir>/source/libSPIRV-Tools.a or <spirv-build-dir>/source/SPIRV-Tools.lib. For optimization, the header file is <spirv-dir>/include/spirv-tools/optimizer.hpp, and the static library is <spirv-build-dir>/source/libSPIRV-Tools-opt.a or <spirv-build-dir>/source/SPIRV-Tools-opt.lib.

  • SPIRV-Tools CMake target: Creates the static library:
    • <spirv-build-dir>/source/libSPIRV-Tools.a on Linux and OS X.
    • <spirv-build-dir>/source/libSPIRV-Tools.lib on Windows.
  • SPIRV-Tools-opt CMake target: Creates the static library:
    • <spirv-build-dir>/source/libSPIRV-Tools-opt.a on Linux and OS X.
    • <spirv-build-dir>/source/libSPIRV-Tools-opt.lib on Windows.

Entry points

The interfaces are still under development, and are expected to change.

There are five main entry points into the library in the C interface:

  • spvTextToBinary: An assembler, translating text to a binary SPIR-V module.
  • spvBinaryToText: A disassembler, translating a binary SPIR-V module to text.
  • spvBinaryParse: The entry point to a binary parser API. It issues callbacks for the header and each parsed instruction. The disassembler is implemented as a client of spvBinaryParse.
  • spvValidate implements the validator functionality. Incomplete
  • spvValidateBinary implements the validator functionality. Incomplete

The C++ interface is comprised of three classes, SpirvTools, Optimizer and Linker, all in the spvtools namespace.

  • SpirvTools provides Assemble, Disassemble, and Validate methods.
  • Optimizer provides methods for registering and running optimization passes.
  • Linker provides methods for combining together multiple binaries.

Command line tools

Command line tools, which wrap the above library functions, are provided to assemble or disassemble shader files. It's a convention to name SPIR-V assembly and binary files with suffix .spvasm and .spv, respectively.

Assembler tool

The assembler reads the assembly language text, and emits the binary form.

The standalone assembler is the executable called spirv-as, and is located in <spirv-build-dir>/tools/spirv-as. The functionality of the assembler is implemented by the spvTextToBinary library function.

  • spirv-as - the standalone assembler
    • <spirv-dir>/tools/as

Use option -h to print help.

Disassembler tool

The disassembler reads the binary form, and emits assembly language text.

The standalone disassembler is the executable called spirv-dis, and is located in <spirv-build-dir>/tools/spirv-dis. The functionality of the disassembler is implemented by the spvBinaryToText library function.

  • spirv-dis - the standalone disassembler
    • <spirv-dir>/tools/dis

Use option -h to print help.

The output includes syntax colouring when printing to the standard output stream, on Linux, Windows, and OS X.

Linker tool

The linker combines multiple SPIR-V binary modules together, resulting in a single binary module as output.

This is a work in progress. The linker does not support OpenCL program linking options related to math flags. (See section 5.6.5.2 in OpenCL 1.2)

  • spirv-link - the standalone linker
    • <spirv-dir>/tools/link

Optimizer tool

The optimizer processes a SPIR-V binary module, applying transformations in the specified order.

This is a work in progress, with initially only few available transformations.

  • spirv-opt - the standalone optimizer
    • <spirv-dir>/tools/opt

Validator tool

Warning: This functionality is under development, and is incomplete.

The standalone validator is the executable called spirv-val, and is located in <spirv-build-dir>/tools/spirv-val. The functionality of the validator is implemented by the spvValidate library function.

The validator operates on the binary form.

  • spirv-val - the standalone validator
    • <spirv-dir>/tools/val

Reducer tool

The reducer shrinks a SPIR-V binary module, guided by a user-supplied interestingness test.

This is a work in progress, with initially only shrinks a module in a few ways.

  • spirv-reduce - the standalone reducer
    • <spirv-dir>/tools/reduce

Run spirv-reduce --help to see how to specify interestingness.

Fuzzer tool

The fuzzer transforms a SPIR-V binary module into a semantically-equivalent SPIR-V binary module by applying transformations in a randomized fashion.

This is a work in progress, with initially only a few semantics-preserving transformations.

  • spirv-fuzz - the standalone fuzzer
    • <spirv-dir>/tools/fuzz

Run spirv-fuzz --help for a detailed list of options.

Control flow dumper tool

The control flow dumper prints the control flow graph for a SPIR-V module as a GraphViz graph.

This is experimental.

  • spirv-cfg - the control flow graph dumper
    • <spirv-dir>/tools/cfg

Diff tool

Warning: This functionality is under development, and is incomplete.

The diff tool produces a diff-style comparison between two SPIR-V modules.

  • spirv-diff - the standalone diff tool
    • <spirv-dir>/tools/diff`

Utility filters

  • spirv-lesspipe.sh - Automatically disassembles .spv binary files for the less program, on compatible systems. For example, set the LESSOPEN environment variable as follows, assuming both spirv-lesspipe.sh and spirv-dis are on your executable search path:

     export LESSOPEN='| spirv-lesspipe.sh "%s"'
    

    Then you page through a disassembled module as follows:

    less foo.spv
    
    • The spirv-lesspipe.sh script will pass through any extra arguments to spirv-dis. So, for example, you can turn off colours and friendly ID naming as follows:
      export LESSOPEN='| spirv-lesspipe.sh "%s" --no-color --raw-id'
      
  • vim-spirv - A vim plugin which supports automatic disassembly of .spv files using the :edit command and assembly using the :write command. The plugin also provides additional features which include; syntax highlighting; highlighting of all ID's matching the ID under the cursor; and highlighting errors where the Instruction operand of OpExtInst is used without an appropriate OpExtInstImport.

  • 50spirv-tools.el - Automatically disassembles '.spv' binary files when loaded into the emacs text editor, and re-assembles them when saved, provided any modifications to the file are valid. This functionality must be explicitly requested by defining the symbol SPIRV_TOOLS_INSTALL_EMACS_HELPERS as follows:

    cmake -DSPIRV_TOOLS_INSTALL_EMACS_HELPERS=true ...
    

    In addition, this helper is only installed if the directory /etc/emacs/site-start.d exists, which is typically true if emacs is installed on the system.

    Note that symbol IDs are not currently preserved through a load/edit/save operation. This may change if the ability is added to spirv-as.

Tests

Tests are only built when googletest is found.

Running test with CMake

Use ctest -j <num threads> to run all the tests. To run tests using all threads:

ctest -j$(nproc)

To run a single test target, use ctest [-j <N>] -R <test regex>. For example, you can run all opt tests with:

ctest -R 'spirv-tools-test_opt'

Running test with Bazel

Use bazel test :all to run all tests. This will run tests in parallel by default.

To run a single test target, specify :my_test_target instead of :all. Test target names get printed when you run bazel test :all. For example, you can run opt_def_use_test with:

on linux:

bazel test --cxxopt=-std=c++17 :opt_def_use_test

on windows:

bazel test --cxxopt=/std:c++17 :opt_def_use_test

Future Work

See the projects pages for more information.

Assembler and disassembler

  • The disassembler could emit helpful annotations in comments. For example:
    • Use variable name information from debug instructions to annotate key operations on variables.
    • Show control flow information by annotating OpLabel instructions with that basic block's predecessors.
  • Error messages could be improved.

Validator

This is a work in progress.

Linker

  • The linker could accept math transformations such as allowing MADs, or other math flags passed at linking-time in OpenCL.
  • Linkage attributes can not be applied through a group.
  • Check decorations of linked functions attributes.
  • Remove dead instructions, such as OpName targeting imported symbols.

Licence

Full license terms are in LICENSE

Copyright (c) 2015-2016 The Khronos Group Inc.

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.

spirv-tools's People

Contributors

afd avatar alan-baker avatar andreperezmaselco avatar antiagainst avatar awoloszyn avatar ben-clayton avatar dependabot[bot] avatar dj2 avatar dneto0 avatar dnovillo avatar ehsannas avatar github-actions[bot] avatar greg-lunarg avatar jaebaek avatar jeffbolznv avatar jeremyg-lunarg avatar keenuts avatar kpet avatar paulthomson avatar pierremoreau avatar qining avatar s-perron avatar sfricke-samsung avatar shabbyx avatar sjfricke avatar spencer-lunarg avatar stefanomil avatar umar456 avatar vasniktel avatar zoddicus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spirv-tools's Issues

Code massage for the test fixture class

The name of TextToBinaryTest[Base] is outdated; we actually have roundtrip test methods inside it. I'd like to change it to RoundTripTest[Base]. And also, rename the methods inside it to something like {Encode|Decode}...{Succeeded|Failed}....

Opinions?

spirv-as reports whole program as the invalid opcode

I assemble a simple program with an incorrect opcode at the end. spirv-as should report just that opcode as invalid, but instead it reports the whole program as the opcode name:

deki@deki-macbookpro>cat bug.spvasm 
OpCapability Shader
OpMemoryModel Logical GLSL450
OpXYZ
deki@deki-macbookpro>./spirv-as bug.spvasm 
error: 3: 1: Invalid Opcode name 'OpCapability Shader
OpMemoryModel Logical GLSL450
OpXYZ'

update_build_version script syntax and str object issues

I'm trying to build SPIRV-Tools under gentoo linux (with python-3.5) and I run into the following issues:

[ 3%] Update build-version.inc in the Spirv-tools build directory (if necessary).
/usr/bin/python3.5 /home/benjamin/Software/SPIRV-Tools/utils/update_build_version.py /home/benjamin/Software/SPIRV-Tools
File "/home/benjamin/Software/SPIRV-Tools/utils/update_build_version.py", line 67
print 'usage: {0} <spirv-tools_dir>'.format(sys.argv[0])
^
SyntaxError: invalid syntax

I commented out line 67 as it is likely not used during build but then I run into this issue:

[ 3%] Update build-version.inc in the Spirv-tools build directory (if necessary).
/usr/bin/python3.5 /home/benjamin/Software/SPIRV-Tools/utils/update_build_version.py /home/benjamin/Software/SPIRV-Tools
Traceback (most recent call last):
File "/home/benjamin/Software/SPIRV-Tools/utils/update_build_version.py", line 76, in
main()
File "/home/benjamin/Software/SPIRV-Tools/utils/update_build_version.py", line 70, in main
new_content = ('"spirv-tools ' + describe(sys.argv[1]).replace('"', '"') + '\n"\n')
TypeError: a bytes-like object is required, not 'str'

As my python experience is extremely limited, I thought I should just file this.

Cannot compile as C library, has to be C++

There is a tiny inconvenience in OpenCL.std.h included by libspirv.h. That OpenCL header file is a C++ header file and so a client including libspirv.h cannot compile as C application, but must use a C++ compiler. (msvc complains when compiling a .c file including spirv-tools\libspirv.h)
Simply guarding the "namespace" directive with an #ifdef __cplusplus , or removing that namespace declaration, helped.

"struct spv_context_t" misses a typedef for C compilation

Including libspirv.h in a C project causes an error at this line :
https://github.com/KhronosGroup/SPIRV-Tools/blob/master/include/spirv-tools/libspirv.h#L344
because spv_context_t isn't a known type, but struct spv_context_t is.

Since libspirv is intended as a C API, this should be fixed by adding
typedef struct spv_context_t spv_context_t; just here :
https://github.com/KhronosGroup/SPIRV-Tools/blob/master/include/spirv-tools/libspirv.h#L334

Get rid of SPV_VALIDATE_*_BITs

Let's discuss whether and how we can get rid of these options. I suspect that the vast majority of users doesn't need sophisticated ways to turn off certain validations. Furthermore, the options are intertwined in unexpected ways -- for instance, multiple validations need _.current_layout_section_, but this is only computed when SPV_VALIDATE_LAYOUT_BIT is set.

Unit tests also shouldn't need fine-grained controls of this kind -- those that do aren't really unit tests. Moreover, it's fishy design to add so much API just for testing purposes.

My opinion is that we should eliminate these controls altogether, perform full validation always, and fix unit tests to have minimally invalid assembly or invoke only specific validations directly.

@umar456 @dneto0 @AWoloszyn ^^

Structured control flow checks should be optional.

My understanding is that SPIR-V v1.0 specification doesn't force control flow to be structured. OpenCL C support things like 'goto' and OpenCL C -> SPIR-V compiler from here produces SPIR-V files with unstructured control flow. These SPIR-V files do not pass structured control flow checks.
Can we make them optional for SPIR-V files produced from OpenCL C?

I attached CL source and SPIR-V file demonstrating the issue.

sample_test.zip

Vulkan conformance test gets access violation in spvValidate

Specifics
Windows 7, Nvidia GTX 660 Ti, Driver 368.39

Have Vulkan SDK 1.0.21 installed for validation layers and set environment variable VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_standard_validation

To reproduce I run all of the dEQP-VK.glsl.functions.control_flow.* tests from the Vulkan Conformance Test Suite

Message:
Exception thrown: read access violation.
this was nullptr. (debugger confirms that variable "this" is NULL)

Location:
BasicBlock.h:

76 /// Returns true if the block is reachable in the CFG
77 bool reachable() const { return reachable_; }

Call Stack:

    VkLayer_core_validation.dll!libspirv::BasicBlock::reachable() Line 77   C++

    VkLayer_core_validation.dll!libspirv::StructuredControlFlowChecks(const libspirv::ValidationState_t & _, const libspirv::Function & function, const std::vector<std::pair<unsigned int,unsigned int>,std::allocator<std::pair<unsigned int,unsigned int> > > & back_edges) Line 349 C++

    VkLayer_core_validation.dll!libspirv::PerformCfgChecks(libspirv::ValidationState_t & _) Line 478    C++

    VkLayer_core_validation.dll!spvValidate(const spv_context_t * const context, spv_const_binary_t * const binary, spv_diagnostic_t * * pDiagnostic) Line 209  C++

    VkLayer_core_validation.dll!core_validation::CreateShaderModule(VkDevice_T * device, const VkShaderModuleCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkShaderModule_T * * pShaderModule) Line 9069  C++

    VkLayer_object_tracker.dll!object_tracker::CreateShaderModule(VkDevice_T * device, const VkShaderModuleCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkShaderModule_T * * pShaderModule) Line 3583    C++

    VkLayer_parameter_validation.dll!parameter_validation::CreateShaderModule(VkDevice_T * device, const VkShaderModuleCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkShaderModule_T * * pShaderModule) Line 2621    C++

    VkLayer_threading.dll!threading::CreateShaderModule(VkDevice_T * device, const VkShaderModuleCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkShaderModule_T * * pShaderModule) Line 1133  C++

    deqp-vk.exe!vk::DeviceDriver::createShaderModule(vk::VkDevice_s * device, const vk::VkShaderModuleCreateInfo * pCreateInfo, const vk::VkAllocationCallbacks * pAllocator, vk::Handle<14> * pShaderModule) Line 218  C++

    deqp-vk.exe!vk::createShaderModule(const vk::DeviceInterface & vk, vk::VkDevice_s * device, const vk::VkShaderModuleCreateInfo * pCreateInfo, const vk::VkAllocationCallbacks * pAllocator) Line 209    C++

    deqp-vk.exe!vk::createShaderModule(const vk::DeviceInterface & deviceInterface, vk::VkDevice_s * device, const vk::ProgramBinary & binary, unsigned int flags) Line 206 C++
    deqp-vk.exe!vkt::`anonymous namespace'::PipelineProgram::PipelineProgram(vkt::Context & context, const glu::sl::ShaderCaseSpecification & spec) Line 745    C++

    deqp-vk.exe!vkt::`anonymous namespace'::ShaderCaseInstance::ShaderCaseInstance(vkt::Context & context, const glu::sl::ShaderCaseSpecification & spec) Line 1410 C++

    deqp-vk.exe!vkt::`anonymous namespace'::ShaderCase::createInstance(vkt::Context & context) Line 1791    C++

    deqp-vk.exe!vkt::TestCaseExecutor::init(tcu::TestCase * testCase, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & casePath) Line 246   C++

    deqp-vk.exe!tcu::TestSessionExecutor::enterTestCase(tcu::TestCase * testCase, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & casePath) Line 181   C++

    deqp-vk.exe!tcu::TestSessionExecutor::iterate() Line 101    C++

    deqp-vk.exe!tcu::App::iterate() Line 172    C++

    deqp-vk.exe!main(int argc, const char * * argv) Line 55 C++
    [External Code] 

Bisected to spirv-tools commit: f61db0b
Validator structured flow checks: back-edge, constructs

Originally posted by @Tony-LunarG in google/shaderc#234:

Add Vulkan validity checks for OpDecorate and OpMemberDecorate in validator

There is a set of non-trivial constraints in SPIR-V & Vulkan specs regarding decorating variables with:

  • location & binding qualifiers
  • interpolation and patch qualifiers
  • offset and alignment

Especially nested interface blocks / structs / arrays need to follow rules defined in "14.1. Shader Input and Output Interfaces" Vulkan spec chapter to get SPIR-V shaders properly "linked" during pipeline creation.

As there are apps (including glslang - KhronosGroup/glslang#269) misusing the decorations it would be good to have these checked in SPIR-V validator.

Mac OSX: parseNumber tests failing for out-of-bound numbers on clang

The following tests are failing for parseNumber using clang++ Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn).:

[  FAILED  ] AssemblyContextParseNarrowUnsignedIntegers.Sample
[  FAILED  ] AssemblyContextParseWideUnsignedIntegers.Sample
[  FAILED  ] AssemblyContextParseFloat.Sample
[  FAILED  ] AssemblyContextParseDouble.Sample

This is because clang does not fail for large numbers(i.e. 1e400) when converting text to float using istringstream.

#include <iostream>
#include <iomanip>
#include <sstream>
#include <limits>
using namespace std;

int main() {
  istringstream text_stream("1e400");
  double val = 0;

  text_stream >> std::setbase(0);
  text_stream >> val;

  cout << text_stream.fail() << endl;
  cout << "val: " << val << endl;
}

Output:

clang++ -std=c++11 foo.cpp -o clang_foo && echo clang && ./clang_foo && g++-4.8 -std=c++11 foo.cpp -o gcc_foo && echo gcc && ./gcc_foo
clang
0
val: inf
gcc
1
val: 1.79769e+308

[SPIRV-Val][OpenCL] Wrong diagnostics of OpLabel layout in function definition/declaration.

I got following error message for the attached SPIR-V file:

error: 25: A function must begin with a label

The disassembled module part looks like this:

     %12 = OpFunction %6 None %11
     %13 = OpFunctionParameter %8
     %14 = OpFunctionParameter %10
     %15 = OpLabel

According to specification function definition layout is:

  • Function definition, using OpFunction.
  • Function parameter declarations, using OpFunctionParameter.
  • Block
  • Block
  • Function end, using OpFunctionEnd.

Block must start with OpLabel instruction.

It looks like SPIR-V validation tools doesn't expect OpFunctionParameter to follow OpFunction instruction.

Function declaration layout check has the same issue.

Expose more of the utility functionality

There is a lot of useful functionality, especially in opcode.h which is currently not exposed via the libspirv.h header.

I'm mostly looking for an easy way to get instruction metadata (e.g. names of instructions and types of operands). I'm generating this myself from the HTML spec at https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html right now, but this is cumbersome to update since the HTML formatting tends to change slightly between versions.

One thing that I found particularly useful while working on https://github.com/bonus2113/otherside/ was having a type for each instruction (see https://github.com/bonus2113/otherside/blob/master/src/shared/lookups_gen.h for an example) which allowed me to easily access operands by name, but that might be out of scope for this project.

spvBinaryParse API deficient: client needs to handle endianness; not easily composable

The spvBinaryParse API isn't quite right:

  1. It requires the client to translate endianness when the module being parsed is of a foreign endiannes. (e.g. I'm on a little-endian machine, but the module is big-endian). Frankly, most clients won't bother to write that code since the world seems dominated by little-endian machines. Also, there is some subtlety to the translation since most values need to be endian-translated, but literal strings do not. This is complexity we don't need.
  2. Composability: The API is space-efficient: It does not copy the data in the underlying module. To get
    values from instructions, the client must have retained the base pointer to the module, and then index into it via the instruction offset and the operand offset. That's fine as far as it goes, but it isn't very composable. For example, suppose you want to chain multiple transforms together. The consumer at
    the end of the pipeline needs a base pointer somewhere to read values out of the instructions. But that means the last transform has to form a pointer relative to some array of words that was meaningful only at the beginning of the pipeline.

I think we can fix both problems in a reasonable way, as follows:
The spv_parsed_instruction_t should gain a "words" member of type "const uint32_t*". It points to native-endian sequence of SPIR-V words for the entire instruction. (So, for example, words[0] contains the combined word count and opcode.) As before, the contract is that the words array is only valid for as long as the callback is excecuting, then may be discarded or overwritten.

In the common case where the original module was in the machine's native endianness, then no copying is required: the words pointer is just computed from the original module's base pointer plus the instruction's offset. In the non-native endian case, there is some copying, but it's done by the parser and not the client. And since the lifetime of the data is restricted to the duration of the callback, we can reuse that space for the next instruction.

With the new design it will become easy to make pipelines of analysis or transform steps in a space efficient way. It should also be generally time efficient since the chain of callbacks should usually be working on the same chunk of instruction storage. It should be hot in the cache.

Operands are treated as literals instead of ids at capability check

In particular during validation of atomic instructions memory semantics operands are treated as literals, but according to the spec they must be id.

In the attached example, it happened that OpAtomicIAdd has memory semantics operand = %64. Literally it corresponds to 0x40 (UniformMemory, which require shader capability). But actually %64 is an id of an integer constant = 0x10(SequentiallyConsistent, no capability required).

%64 = OpConstant %2 16
...
%63 = OpAtomicIAdd %2 %50 %35 %64 %35

This causes false positive errors to be reported by spirv-val tool:

error: 129: Operand 5 of AtomicIAdd requires one of these capabilities: Shader

atomic_exchange.global_atomic_double_declared_in_program.used_in_generic_function.order_relaxed.spv20_32.zip

atomic_exchange.global_atomic_double_declared_in_program.used_in_generic_function.order_relaxed.spv20_32.txt

spvTextToBinary cannot handle CR+LF unless fread is used by client

I built a small DLL using the SPIRV-Tools.lib library to allow another language to call into SPIRV-Tools using a foreign-function interface of that language to call into C libraries.
The function in the DLL accepted a single memory pointer to the assembly text, which was loaded by the client program before calling into the DLL and eventually into spvTextToBinary.
This assembly text was read from a file as is, and not via fread, which in "r" text mode apparently converts CR+LF to LF under msvc 14.
The function spvTextToBinary() seems to be unable to handle CR+LF linebreaks in the source assembly text.
The spirv-as assembly tool works flawlessly, though, because fread (in "r" text mode) converts CR+LF to LF (\n).
But it does not work when using other mechanism that read the file as is without any conversion of line-breaks.

So the current workaround is to force the client of spvTextToBinary() to convert CR+LF to LF before handing the assembly text to spvTextToBinary.

Error message I am getting for the example in the SPIR-V specification:

error: 6: 1: Expected <opcode> or <result-id> at the beginning of an instruction, found '
'.

OpDecorate should not allow an arbitrary number of arguments

The following should assemble, but should not disassemble.

   OpDecorate %1 LinkageAttributes "abc" !1 !0

The !1 is 1, which is interpreted as linkage attribute "Import". The instruction ends up having 6 words, the last being value 0.
However, the binary parser (and disassembler) should reject this input because that last !0 word is extraneous.

The root cause is that the grammar in opcode.inc has a last operand class of OperandVariableLiterals, so that expands to zero or more literals. Instead that should be dropped, and we should allow processing of the decoration enum word to add just the right number and type of operands to the operand pattern.

Float parsing fails tests on Windows.

Somewhat related to #45 . Fixes for that caused me to change the parser (to work around C++ library bugs on Mac). I also added tests to validate expected behaviour when parsing overflow numbers and non-numbers.

But those tests are now failing on Windows.
See AppVeyor results from github from testing github.com/google/shaderc
https://ci.appveyor.com/project/dneto0/shaderc/build/288/job/et8t59ppbyoe74n7
It appears that std::operator>>(float&) is broken on edge cases on that MSVC compiler and runtime.

[ RUN      ] FloatParse/ParseNormalFloatTest.Samples/1
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1033): error: Value of: parsed_value.value()
Expected: is equal to 0
  Actual: -0x1p-149
 literal: abc negate: true
[  FAILED  ] FloatParse/ParseNormalFloatTest.Samples/1, where GetParam() = 32-byte object <61-62 63-00 6F-46 33-32 2F-48 65-78 46-6C 6F-61 03-00 00-00 0F-00 00-00 01-00 65-73 00-00 00-00> (0 ms)

...

 RUN      ] FloatParse/ParseNormalFloatTest.Samples/14
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1033): error: Value of: parsed_value.value()
Expected: is equal to 3.40282e+38
  Actual: 0
 literal: 1e40 negate: false
[  FAILED  ] FloatParse/ParseNormalFloatTest.Samples/14, where GetParam() = 32-byte object <31-65 34-30 00-65 73-2F 31-33 65-78 46-6C 6F-61 04-00 00-00 0F-00 00-00 00-00 65-73 FF-FF 7F-7F> (0 ms)
[ RUN      ] FloatParse/ParseNormalFloatTest.Samples/15
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1033): error: Value of: parsed_value.value()
Expected: is equal to -3.40282e+38
  Actual: -0x1p-149
 literal: 1e40 negate: true 
[  FAILED  ] FloatParse/ParseNormalFloatTest.Samples/15, where GetParam() = 32-byte object <31-65 34-30 00-65 73-2F 31-33 65-78 46-6C 6F-61 04-00 00-00 0F-00 00-00 01-00 65-73 FF-FF 7F-FF> (1 ms)
[ RUN      ] FloatParse/ParseNormalFloatTest.Samples/16
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1033): error: Value of: parsed_value.value()
Expected: is equal to -3.40282e+38
  Actual: 0
 literal: -1e40 negate: false
[  FAILED  ] FloatParse/ParseNormalFloatTest.Samples/16, where GetParam() = 32-byte object <2D-31 65-34 30-00 73-2F 31-35 65-78 46-6C 6F-61 05-00 00-00 0F-00 00-00 00-00 65-73 FF-FF 7F-FF> (0 ms)

and

[ RUN      ] Float16Parse/ParseNormalFloat16Test.Samples/1
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1098): error: Value of: parsed_value.value()
Expected: is equal to 0x0p+0
  Actual: -0x0p+0
 literal: abc negate: true
[  FAILED  ] Float16Parse/ParseNormalFloat16Test.Samples/1, where GetParam() = 28-byte object <61-62 63-00 74-50 61-72 73-65 2F-50 61-72 73-65 03-00 00-00 0F-00 00-00 01-00 00-00> (0 ms)
[ RUN      ] Float16Parse/ParseNormalFloat16Test.Samples/2

and

 RUN      ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/5
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1145): error: Value of: value.value().getAsFloat()
Expected: is equal to 3.40282e+38
  Actual: 0 (of type float)
[  FAILED  ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/5, where GetParam() = 32-byte object <31-65 34-30 00-00 73-2F 31-32 2F-50 61-72 73-65 04-00 00-00 0F-00 00-00 00-00 00-00 FF-FF 7F-7F> (0 ms)
[ RUN      ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/6
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1145): error: Value of: value.value().getAsFloat()
Expected: is equal to -3.40282e+38
  Actual: -1.4013e-45 (of type float)
[  FAILED  ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/6, where GetParam() = 32-byte object <2D-31 65-34 30-00 73-2F 31-32 2F-50 61-72 73-65 05-00 00-00 0F-00 00-00 00-00 00-00 FF-FF 7F-FF> (0 ms)
[ RUN      ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/7
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1145): error: Value of: value.value().getAsFloat()
Expected: is equal to 3.40282e+38
  Actual: 0 (of type float)
[  FAILED  ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/7, where GetParam() = 32-byte object <31-65 34-30 30-00 73-2F 31-32 2F-50 61-72 73-65 05-00 00-00 0F-00 00-00 00-00 00-00 FF-FF 7F-7F> (0 ms)
[ RUN      ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/8
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1145): error: Value of: value.value().getAsFloat()
Expected: is equal to -3.40282e+38
  Actual: -1.4013e-45 (of type float)
[  FAILED  ] FloatOverflow/FloatProxyParseOverflowFloatTest.Sample/8, where GetParam() = 32-byte object <2D-31 65-34 30-30 00-2F 31-32 2F-50 61-72 73-65 06-00 00-00 0F-00 00-00 00-00 00-00 FF-FF 7F-FF> (0 ms)
[----------] 9 tests from FloatOverflow/FloatProxyParseOverflowFloatTest (1 ms total)

and

 RUN      ] DoubleOverflow/FloatProxyParseOverflowDoubleTest.Sample/7
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1170): error: Value of: value.value().getAsFloat()
Expected: is equal to 1.79769e+308
  Actual: 1.53657e-304 (of type double)
[  FAILED  ] DoubleOverflow/FloatProxyParseOverflowDoubleTest.Sample/7, where GetParam() = 40-byte object <31-65 34-30 30-00 1D-01 60-C7 1D-01 01-00 00-00 05-00 00-00 0F-00 00-00 00-00 00-00 00-00 00-00 FF-FF FF-FF FF-FF EF-7F> (0 ms)
[ RUN      ] DoubleOverflow/FloatProxyParseOverflowDoubleTest.Sample/8
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1170): error: Value of: value.value().getAsFloat()
Expected: is equal to -1.79769e+308
  Actual: -1.53657e-304 (of type double)
[  FAILED  ] DoubleOverflow/FloatProxyParseOverflowDoubleTest.Sample/8, where GetParam() = 40-byte object <2D-31 65-34 30-30 00-00 00-00 00-00 00-00 00-00 06-00 00-00 0F-00 00-00 00-00 00-00 00-00 00-00 FF-FF FF-FF FF-FF EF-FF> (1 ms)
[----------] 9 tests from DoubleOverflow/FloatProxyParseOverflowDoubleTest (1 ms total)

and

 RUN      ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/5
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1194): error: Expected: (GetParam().expect_success) != (input.fail()), actual: true vs true
 literal: 1e40
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1196): error: Value of: value.value().data()
Expected: is equal to 31744
  Actual: 0 (of type unsigned short)
 literal: 1e40
[  FAILED  ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/5, where GetParam() = 28-byte object <31-65 34-30 00-00 2F-32 76-65 72-66 6C-6F 77-2F 04-00 00-00 0F-00 00-00 01-00 00-7C> (0 ms)
[ RUN      ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/6
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1194): error: Expected: (GetParam().expect_success) != (input.fail()), actual: true vs true
 literal: 1e400
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1196): error: Value of: value.value().data()
Expected: is equal to 31744
  Actual: 0 (of type unsigned short)
 literal: 1e400
[  FAILED  ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/6, where GetParam() = 28-byte object <31-65 34-30 30-00 2F-32 76-65 72-66 6C-6F 77-2F 05-00 00-00 0F-00 00-00 01-00 00-7C> (1 ms)
[ RUN      ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/7
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1194): error: Expected: (GetParam().expect_success) != (input.fail()), actual: true vs true
 literal: -1e40
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1196): error: Value of: value.value().data()
Expected: is equal to 64512
  Actual: 32768 (of type unsigned short)
 literal: -1e40
[  FAILED  ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/7, where GetParam() = 28-byte object <2D-31 65-34 30-00 2F-32 76-65 72-66 6C-6F 77-2F 05-00 00-00 0F-00 00-00 01-00 00-FC> (0 ms)
[ RUN      ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/8
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1194): error: Expected: (GetParam().expect_success) != (input.fail()), actual: true vs true
 literal: -1e400
C:\projects\shaderc\third_party\spirv-tools\test\HexFloat.cpp(1196): error: Value of: value.value().data()
Expected: is equal to 64512
  Actual: 32768 (of type unsigned short)
 literal: -1e400
[  FAILED  ] Float16Overflow/FloatProxyParseOverflowFloat16Test.Sample/8, where GetParam() = 28-byte object <2D-31 65-34 30-30 00-32 76-65 72-66 6C-6F 77-2F 06-00 00-00 0F-00 00-00 01-00 00-FC> (0 ms)
[----------] 9 tests from Float16Overflow/FloatProxyParseOverflowFloat16Test (1 ms total)

Assembler, bin parser: Extended instructions allowed to have too many parameters

The parser is allowing an extended instruction to have too many parameters.
For example, the OpenCL pow instruction is only supposed to have two normal arguments, but the following is accepted by the assembler, and the result is happily disassembled by the binary-parser/disassembler.

          %1 = OpExtInstImport "OpenCL.std"
          %blam  = OpExtInst %a %1 pow %x %y %z
          OpNop

The %z argument should have triggered an error.

SpecId decoration on front-end constant (not spec constant) is not considered as invalid code

Example code:

               OpCapability Shader
               OpCapability Float64
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Vertex %main "main"
               OpSource GLSL 450
               OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
               OpSourceExtension "GL_GOOGLE_include_directive"
               OpName %main "main"
               OpDecorate %7 SpecId 200
               OpDecorate %9 SpecId 201
               OpDecorate %11 SpecId 202
               OpDecorate %13 SpecId 203
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
        %int = OpTypeInt 32 1
          %7 = OpConstant %int 3
      %float = OpTypeFloat 32
          %9 = OpConstant %float 3.14
     %double = OpTypeFloat 64
         %11 = OpConstant %double 3.14159265358979
       %bool = OpTypeBool
         %13 = OpConstantTrue %bool
       %main = OpFunction %void None %3
          %5 = OpLabel
               OpReturn
               OpFunctionEnd

This code is invalid as SpecId should not be used to decorate a normal constant. But spirv-val does not alert on this case.

Validator does not consider type aliasing with structs in interface blocks

When writing structs to an SSBO this validation error triggers:

error: 196: OpStore Pointer <id> '10's type does not match Object <id> '11's type.

SPIR-V:

; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 1
; Bound: 25
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %4 "main"
               OpExecutionMode %4 LocalSize 1 1 1
               OpSource ESSL 310
               OpName %4 "main"
               OpName %8 "MyStruct"
               OpMemberName %8 0 "foo"
               OpName %10 "bar"
               OpName %11 "MyStruct"
               OpMemberName %11 0 "foo"
               OpName %12 "SSBO0"
               OpMemberName %12 0 "foo_std430"
               OpName %14 ""
               OpName %20 "SSBO1"
               OpMemberName %20 0 "foo_std430_out"
               OpName %22 ""
               OpMemberDecorate %11 0 Offset 0
               OpMemberDecorate %12 0 Offset 0
               OpDecorate %12 BufferBlock
               OpDecorate %14 DescriptorSet 0
               OpDecorate %14 Binding 0
               OpMemberDecorate %20 0 Offset 0
               OpDecorate %20 BufferBlock
               OpDecorate %22 DescriptorSet 0
               OpDecorate %22 Binding 1
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 4
          %8 = OpTypeStruct %7
          %9 = OpTypePointer Function %8
         %11 = OpTypeStruct %7
         %12 = OpTypeStruct %11
         %13 = OpTypePointer Uniform %12
         %14 = OpVariable %13 Uniform
         %15 = OpTypeInt 32 1
         %16 = OpConstant %15 0
         %17 = OpTypePointer Uniform %11
         %20 = OpTypeStruct %11
         %21 = OpTypePointer Uniform %20
         %22 = OpVariable %21 Uniform
          %4 = OpFunction %2 None %3
          %5 = OpLabel
         %10 = OpVariable %9 Function
         %18 = OpAccessChain %17 %14 %16
         %19 = OpLoad %11 %18
               OpStore %10 %19
         %23 = OpLoad %8 %10
         %24 = OpAccessChain %17 %22 %16
               OpStore %24 %23
               OpReturn
               OpFunctionEnd

Generated from this glslang output:

#version 310 es
layout(local_size_x = 1) in;

struct MyStruct
{
    vec4 foo;
};

layout(binding = 0, std430) buffer SSBO0
{
    MyStruct foo_std430;
};

layout(binding = 1, std430) buffer SSBO1
{
    MyStruct foo_std430_out;
};

void main()
{
    MyStruct bar = foo_std430;
    foo_std430_out = bar;
}

validator: goes into infinite loop when a block branches to itself and nothing else

Triggered by this input:

           OpCapability Shader
           OpMemoryModel Logical GLSL450
%voidt   = OpTypeVoid
%funct   = OpTypeFunction %voidt

%blah    = OpFunction %voidt None %funct
%entry   = OpLabel
           OpBranch %loop
%loop    = OpLabel
           OpLoopMerge %exit %loop None
           OpBranch %loop
%exit    = OpLabel
           OpReturn
           OpFunctionEnd

It's stuck in libspirv::CalculateDominators

Fix use of relative include paths in libspirv.h

libspirv.h currently includes the spirv headers from "headers/...". This is inconvenient in a public header like this as it makes all code including it need to have an additional include path set up to the spirv-tools/external/include/ path.

An easy fix would be to remove the "headers/" from the include paths such that projects need only set up an include path for spirv (which they most likely already have, or can do in a variety of ways).

If SPIRV-Tools may need non-standard modifications to the headers and cannot use the existing ones someone may have then changing the includes to be unambiguous and relative to libspirv.h would make more sense ("../../external/includes/headers/...").

Validator: def-use error incorrectly generated when the use is in an OpPhi

This affects a Vulkan CTS test.

The essence of the case is:

           OpCapability Shader
           OpMemoryModel Logical GLSL450

           OpName %copy "copy"
           OpName %false "false"
           OpName %if_true "if_true"
           OpName %exit "exit"

%voidt   = OpTypeVoid
%funct   = OpTypeFunction %voidt
%boolt   = OpTypeBool
%false   = OpConstantFalse %boolt

%main    = OpFunction %voidt None %funct
%entry   = OpLabel
           OpSelectionMerge %exit None
           OpBranchConditional %false %if_true %exit

%if_true = OpLabel
%copy    = OpCopyObject %boolt %false
           OpBranch %exit

%exit    = OpLabel
%v       = OpPhi %boolt %false %entry %copy %if_true
           OpReturn
           OpFunctionEnd

The error reported is: error: 21: ID 1[copy] defined in block 3[if_true] does not dominate its use in block 4[exit]

Parsing problem when file doesn't end in EOL

Running spirv-as on the attached file yields:

error: 21: 1: Invalid Opcode name 'OpCapability Shader
OpMemoryModel Logical GLSL450

%i32 = OpTypeInt 32 1
%f32 = OpTypeFloat 32
%v4i32 = OpTypeVector %i32 4
%timg = OpTypeImage %i32 2D 0 0 0 0 Unknown
%pimg = OpTypePointer Input %timg
%tfun = OpTypeFunction %i32

%vimg = OpVariable %pimg Input
%coord = OpConstant %i32 0
%bias = OpConstant %f32 0.

%main = OpFunction %i32 None %tfun
%lbl = OpLabel
%img = OpLoad %timg %vimg
%r1 = OpImageFetch %v4i32 %img %coord Offset|Bias %bias %bias
;%r2 = OpImageSampleExplicitLod %v4i32 %sample %coord Bias 0.2
OpReturnValue %coord
OpFunctionEndѷ'

IOW, it thinks the whole program is an opcode name. 🙀

shader.txt

Literal string endianness is handled incorrectly

The code currently assumes that strings can be directly read in and written to disk without being swapped, but this isn't true. The SPIR-V spec, in the definition of "literal string" (section 2.2.1), says that "the UTF-8 octets (8-bit bytes) are packed four per word, following the little-endian convention (i.e., the first octet is in the lowest-order 8 bits of the word)." That is, literal strings are defined in terms of words, just like everything else in SPIR-V. While the way that bytes on-disk get transformed to words isn't defined by the spec, it wouldn't make any sense to define it "just so" so that the way SPIR-V Tools is currently parsing the SPIR-V would be correct, since it would make the definition in section 2.2.1 confusing and meaningless, and I can say that that wasn't the intent when the language in section 2.2.1 was added. That is, it's expected that when reading from byte-oriented formats, if the magic word is flipped, then the entire module is flipped. Practically, this also makes loading SPIR-V from disk in games much easier, since they don't need to know about what's a string vs. what isn't -- just check the magic word and flip the bytes if necessary.

spirv-as fails to recognize spec example

The SPIR-V example on the SPIR-V specification (under 'Corresponding SPIR-V:') is rejected with saying error: 123: 16: Invalid Opcode name '; Magic: 0x07230203 (SPIR-V).

When I remove the comment lines starting with a semicolon, then I get the following output:
error: 119: 16: Invalid Opcode name '
the source file has as very last line OpFunctionEnd

If I add a single line break to the file, it works. I think that line break problem is described by #126.

Add check for Image arg to OpImageFetch

The Image arg to OpImageFetch must be of type OpTypeImage. Currently OpSampledImage is not causing an error. glslang was previously generating OpSampledImage value but is now adding an OpImage operator.

need a C++ API

The SPIR-V Tools API is a C API to provide ABI stability and a lowest-common-denominator target for multiple languages. However, it's begging for a more convenient C++ API.

提议

希望增加visual studio 工程项目。
把一个需要到的文件都放到一个项目里,这样的话也方便了新手 嗯

Add an OpenGL enum values in spv_target_env

There's now an extension to GL to allow use of SPIR-V for shader programs:
https://www.opengl.org/registry/specs/ARB/gl_spirv.txt

We probably need to add entries to spv_target_env for any GL-based environments that will use SPIR-V. The gl_spirv extension provides validation rules.

The extension describes validation rules in seciton "A.spv.2" and allows for variations for OpenGL 4.0, 4.1, 4.2, 4.3, 4.5 due to progression of functionality in those specs.

spvTextToBinary to return a mapping of textual ID names to numeric IDs

Use Case:
Unit test in the validation rely on the error codes validate the result of the spvValidate function. Ideally the tests should check both the error code and the diagnostic message to verify that the test case has accurately passed. This is currently not possible because the named ID representation is lost during the Text to Binary conversion.

The spvTextToBinary function should return a map which contains a mapping from ID to ID names used in the textual representation of the SPIR-V.

[SPIRV-Val][OpenCL] Incorrect check on using OpTypePointer.

I got following error for the attached SPIR-V file:

error: 350: OpReturnValue value's type <id> '10' is a pointer, but a pointer can only be an operand to OpLoad, OpStore, OpAccessChain, or OpInBoundsAccessChain.

The list of the instructions accepting pointer operands is too short. There are a lot more instructions (especially with Kernel capability) that have pointer operands.

GetModuleOrder() result has unspecified order of destruction

Currently, GetModuleOrder() returns a reference to a static vector object. This is a violation of the style guide because other static objects may accidentally dereference this in their destructors, without any guarantee that the GetModuleOrder vector isn't already destroyed. Instead of creating a static vector, the method should either use a C array or a static pointer to a dynamically allocated vector.

References:
https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
https://isocpp.org/wiki/faq/ctors#construct-on-first-use-v2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.