• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

cmake/H15-Jan-2021-74

gn/H15-Jan-2021-6457

include/spirv_cross/H15-Jan-2021-1,094813

pkg-config/H15-Jan-2021-1411

reference/H15-Jan-2021-96,29582,138

samples/cpp/H15-Jan-2021-392224

shaders/H15-Jan-2021-14,34812,784

shaders-hlsl/H15-Jan-2021-5,1424,579

shaders-hlsl-no-opt/H15-Jan-2021-3,4323,196

shaders-msl/H15-Jan-2021-13,16311,700

shaders-msl-no-opt/H15-Jan-2021-11,23010,145

shaders-no-opt/H15-Jan-2021-7,7837,411

shaders-other/H15-Jan-2021-6663

shaders-reflection/H15-Jan-2021-1,1511,049

shaders-ue4/asm/H15-Jan-2021-20,95020,915

shaders-ue4-no-opt/asm/H15-Jan-2021-3,1063,102

tests-other/H03-May-2022-955748

.clang-formatH A D15-Jan-20215.8 KiB168113

.gitignoreH A D15-Jan-2021161 2119

.travis.ymlH A D15-Jan-20212.6 KiB7366

CODE_OF_CONDUCT.mdH A D15-Jan-2021280 21

GLSL.std.450.hH A D15-Jan-20214 KiB13290

LICENSEH A D15-Jan-202111.1 KiB203169

MakefileH A D15-Jan-2021824 4227

README.mdH A D15-Jan-202120.8 KiB517365

appveyor.ymlH A D15-Jan-2021684 3222

build_glslang_spirv_tools.shH A D15-Jan-2021606 2719

checkout_glslang_spirv_tools.shH A D15-Jan-20211.4 KiB5646

format_all.shH A D15-Jan-2021224 95

main.cppH A D15-Jan-202166.2 KiB1,6461,440

spirv.hH A D15-Jan-2021110 KiB2,1932,090

spirv.hppH A D15-Jan-2021104.1 KiB2,2042,102

spirv_cfg.cppH A D15-Jan-202113.4 KiB405271

spirv_cfg.hppH A D15-Jan-20213.7 KiB164115

spirv_common.hppH A D15-Jan-202143.5 KiB1,8081,287

spirv_cpp.cppH A D15-Jan-202115.7 KiB559422

spirv_cpp.hppH A D15-Jan-20212.6 KiB9452

spirv_cross.cppH A D15-Jan-2021142.1 KiB4,9473,762

spirv_cross.hppH A D15-Jan-202146.2 KiB1,086584

spirv_cross_c.cppH A D15-Jan-202178.9 KiB2,5152,160

spirv_cross_c.hH A D15-Jan-202146.2 KiB993649

spirv_cross_containers.hppH A D15-Jan-202117.3 KiB748579

spirv_cross_error_handling.hppH A D15-Jan-20212.6 KiB9560

spirv_cross_parsed_ir.cppH A D15-Jan-202124.2 KiB1,065850

spirv_cross_parsed_ir.hppH A D15-Jan-20218.7 KiB250146

spirv_cross_util.cppH A D15-Jan-20212.6 KiB7844

spirv_cross_util.hppH A D15-Jan-20211.4 KiB3811

spirv_glsl.cppH A D15-Jan-2021491.4 KiB15,61412,350

spirv_glsl.hppH A D15-Jan-202140.4 KiB909645

spirv_hlsl.cppH A D15-Jan-2021169.7 KiB5,8334,783

spirv_hlsl.hppH A D15-Jan-202114.8 KiB376224

spirv_msl.cppH A D15-Jan-2021526.2 KiB14,94812,154

spirv_msl.hppH A D15-Jan-202147.8 KiB1,093728

spirv_parser.cppH A D15-Jan-202130.4 KiB1,200907

spirv_parser.hppH A D15-Jan-20212.5 KiB10263

spirv_reflect.cppH A D15-Jan-202121.2 KiB707575

spirv_reflect.hppH A D15-Jan-20212.4 KiB9253

test_shaders.pyH A D15-Jan-202134.9 KiB914757

test_shaders.shH A D15-Jan-20211.5 KiB3023

update_test_shaders.shH A D15-Jan-202141 51

README.md

1# SPIRV-Cross
2
3SPIRV-Cross is a tool designed for parsing and converting SPIR-V to other shader languages.
4
5[![Build Status](https://travis-ci.org/KhronosGroup/SPIRV-Cross.svg?branch=master)](https://travis-ci.org/KhronosGroup/SPIRV-Cross)
6[![Build Status](https://ci.appveyor.com/api/projects/status/github/KhronosGroup/SPIRV-Cross?svg=true&branch=master)](https://ci.appveyor.com/project/HansKristian-Work/SPIRV-Cross)
7
8## Features
9
10  - Convert SPIR-V to readable, usable and efficient GLSL
11  - Convert SPIR-V to readable, usable and efficient Metal Shading Language (MSL)
12  - Convert SPIR-V to readable, usable and efficient HLSL
13  - Convert SPIR-V to debuggable C++ [DEPRECATED]
14  - Convert SPIR-V to a JSON reflection format [EXPERIMENTAL]
15  - Reflection API to simplify the creation of Vulkan pipeline layouts
16  - Reflection API to modify and tweak OpDecorations
17  - Supports "all" of vertex, fragment, tessellation, geometry and compute shaders.
18
19SPIRV-Cross tries hard to emit readable and clean output from the SPIR-V.
20The goal is to emit GLSL or MSL that looks like it was written by a human and not awkward IR/assembly-like code.
21
22NOTE: Individual features are expected to be mostly complete, but it is possible that certain obscure GLSL features are not yet supported.
23However, most missing features are expected to be "trivial" improvements at this stage.
24
25## Building
26
27SPIRV-Cross has been tested on Linux, iOS/OSX, Windows and Android. CMake is the main build system.
28
29### Linux and macOS
30
31Building with CMake is recommended, as it is the only build system which is tested in continuous integration.
32It is also the only build system which has install commands and other useful build system features.
33
34However, you can just run `make` on the command line as a fallback if you only care about the CLI tool.
35
36A non-ancient GCC (4.8+) or Clang (3.x+) compiler is required as SPIRV-Cross uses C++11 extensively.
37
38### Windows
39
40Building with CMake is recommended, which is the only way to target MSVC.
41MinGW-w64 based compilation works with `make` as a fallback.
42
43### Android
44
45SPIRV-Cross is only useful as a library here. Use the CMake build to link SPIRV-Cross to your project.
46
47### C++ exceptions
48
49The make and CMake build flavors offer the option to treat exceptions as assertions. To disable exceptions for make just append `SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=1` to the command line. For CMake append `-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=ON`. By default exceptions are enabled.
50
51### Static, shared and CLI
52
53You can use `-DSPIRV_CROSS_STATIC=ON/OFF` `-DSPIRV_CROSS_SHARED=ON/OFF` `-DSPIRV_CROSS_CLI=ON/OFF` to control which modules are built (and installed).
54
55## Usage
56
57### Using the C++ API
58
59The C++ API is the main API for SPIRV-Cross. For more in-depth documentation than what's provided in this README,
60please have a look at the [Wiki](https://github.com/KhronosGroup/SPIRV-Cross/wiki).
61**NOTE**: This API is not guaranteed to be ABI-stable, and it is highly recommended to link against this API statically.
62The API is generally quite stable, but it can change over time, see the C API for more stability.
63
64To perform reflection and convert to other shader languages you can use the SPIRV-Cross API.
65For example:
66
67```c++
68#include "spirv_glsl.hpp"
69#include <vector>
70#include <utility>
71
72extern std::vector<uint32_t> load_spirv_file();
73
74int main()
75{
76	// Read SPIR-V from disk or similar.
77	std::vector<uint32_t> spirv_binary = load_spirv_file();
78
79	spirv_cross::CompilerGLSL glsl(std::move(spirv_binary));
80
81	// The SPIR-V is now parsed, and we can perform reflection on it.
82	spirv_cross::ShaderResources resources = glsl.get_shader_resources();
83
84	// Get all sampled images in the shader.
85	for (auto &resource : resources.sampled_images)
86	{
87		unsigned set = glsl.get_decoration(resource.id, spv::DecorationDescriptorSet);
88		unsigned binding = glsl.get_decoration(resource.id, spv::DecorationBinding);
89		printf("Image %s at set = %u, binding = %u\n", resource.name.c_str(), set, binding);
90
91		// Modify the decoration to prepare it for GLSL.
92		glsl.unset_decoration(resource.id, spv::DecorationDescriptorSet);
93
94		// Some arbitrary remapping if we want.
95		glsl.set_decoration(resource.id, spv::DecorationBinding, set * 16 + binding);
96	}
97
98	// Set some options.
99	spirv_cross::CompilerGLSL::Options options;
100	options.version = 310;
101	options.es = true;
102	glsl.set_options(options);
103
104	// Compile to GLSL, ready to give to GL driver.
105	std::string source = glsl.compile();
106}
107```
108
109### Using the C API wrapper
110
111To facilitate C compatibility and compatibility with foreign programming languages, a C89-compatible API wrapper is provided. Unlike the C++ API,
112the goal of this wrapper is to be fully stable, both API and ABI-wise.
113This is the only interface which is supported when building SPIRV-Cross as a shared library.
114
115An important point of the wrapper is that all memory allocations are contained in the `spvc_context`.
116This simplifies the use of the API greatly. However, you should destroy the context as soon as reasonable,
117or use `spvc_context_release_allocations()` if you intend to reuse the `spvc_context` object again soon.
118
119Most functions return a `spvc_result`, where `SPVC_SUCCESS` is the only success code.
120For brevity, the code below does not do any error checking.
121
122```c
123#include <spirv_cross_c.h>
124
125const SpvId *spirv = get_spirv_data();
126size_t word_count = get_spirv_word_count();
127
128spvc_context context = NULL;
129spvc_parsed_ir ir = NULL;
130spvc_compiler compiler_glsl = NULL;
131spvc_compiler_options options = NULL;
132spvc_resources resources = NULL;
133const spvc_reflected_resource *list = NULL;
134const char *result = NULL;
135size_t count;
136size_t i;
137
138// Create context.
139spvc_context_create(&context);
140
141// Set debug callback.
142spvc_context_set_error_callback(context, error_callback, userdata);
143
144// Parse the SPIR-V.
145spvc_context_parse_spirv(context, spirv, word_count, &ir);
146
147// Hand it off to a compiler instance and give it ownership of the IR.
148spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler_glsl);
149
150// Do some basic reflection.
151spvc_compiler_create_shader_resources(compiler_glsl, &resources);
152spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
153
154for (i = 0; i < count; i++)
155{
156    printf("ID: %u, BaseTypeID: %u, TypeID: %u, Name: %s\n", list[i].id, list[i].base_type_id, list[i].type_id,
157           list[i].name);
158    printf("  Set: %u, Binding: %u\n",
159           spvc_compiler_get_decoration(compiler_glsl, list[i].id, SpvDecorationDescriptorSet),
160           spvc_compiler_get_decoration(compiler_glsl, list[i].id, SpvDecorationBinding));
161}
162
163// Modify options.
164spvc_compiler_create_compiler_options(context, &options);
165spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 330);
166spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_FALSE);
167spvc_compiler_install_compiler_options(compiler_glsl, options);
168
169spvc_compiler_compile(compiler, &result);
170printf("Cross-compiled source: %s\n", result);
171
172// Frees all memory we allocated so far.
173spvc_context_destroy(context);
174```
175
176### Linking
177
178#### CMake add_subdirectory()
179
180This is the recommended way if you are using CMake and want to link against SPIRV-Cross statically.
181
182#### Integrating SPIRV-Cross in a custom build system
183
184To add SPIRV-Cross to your own codebase, just copy the source and header files from root directory
185and build the relevant .cpp files you need. Make sure to build with C++11 support, e.g. `-std=c++11` in GCC and Clang.
186Alternatively, the Makefile generates a libspirv-cross.a static library during build that can be linked in.
187
188#### Linking against SPIRV-Cross as a system library
189
190It is possible to link against SPIRV-Cross when it is installed as a system library,
191which would be mostly relevant for Unix-like platforms.
192
193##### pkg-config
194
195For Unix-based systems, a pkg-config is installed for the C API, e.g.:
196
197```
198$ pkg-config spirv-cross-c-shared --libs --cflags
199-I/usr/local/include/spirv_cross -L/usr/local/lib -lspirv-cross-c-shared
200```
201
202##### CMake
203
204If the project is installed, it can be found with `find_package()`, e.g.:
205
206```
207cmake_minimum_required(VERSION 3.5)
208set(CMAKE_C_STANDARD 99)
209project(Test LANGUAGES C)
210
211find_package(spirv_cross_c_shared)
212if (spirv_cross_c_shared_FOUND)
213        message(STATUS "Found SPIRV-Cross C API! :)")
214else()
215        message(STATUS "Could not find SPIRV-Cross C API! :(")
216endif()
217
218add_executable(test test.c)
219target_link_libraries(test spirv-cross-c-shared)
220```
221
222test.c:
223```c
224#include <spirv_cross_c.h>
225
226int main(void)
227{
228        spvc_context context;
229        spvc_context_create(&context);
230        spvc_context_destroy(context);
231}
232```
233
234### CLI
235
236The CLI is suitable for basic cross-compilation tasks, but it cannot support the full flexibility that the API can.
237Some examples below.
238
239#### Creating a SPIR-V file from GLSL with glslang
240
241```
242glslangValidator -H -V -o test.spv test.frag
243```
244
245#### Converting a SPIR-V file to GLSL ES
246
247```
248glslangValidator -H -V -o test.spv shaders/comp/basic.comp
249./spirv-cross --version 310 --es test.spv
250```
251
252#### Converting to desktop GLSL
253
254```
255glslangValidator -H -V -o test.spv shaders/comp/basic.comp
256./spirv-cross --version 330 --no-es test.spv --output test.comp
257```
258
259#### Disable prettifying optimizations
260
261```
262glslangValidator -H -V -o test.spv shaders/comp/basic.comp
263./spirv-cross --version 310 --es test.spv --output test.comp --force-temporary
264```
265
266### Using shaders generated from C++ backend
267
268Please see `samples/cpp` where some GLSL shaders are compiled to SPIR-V, decompiled to C++ and run with test data.
269Reading through the samples should explain how to use the C++ interface.
270A simple Makefile is included to build all shaders in the directory.
271
272### Implementation notes
273
274When using SPIR-V and SPIRV-Cross as an intermediate step for cross-compiling between high level languages there are some considerations to take into account,
275as not all features used by one high-level language are necessarily supported natively by the target shader language.
276SPIRV-Cross aims to provide the tools needed to handle these scenarios in a clean and robust way, but some manual action is required to maintain compatibility.
277
278#### HLSL source to GLSL
279
280##### HLSL entry points
281
282When using SPIR-V shaders compiled from HLSL, there are some extra things you need to take care of.
283First make sure that the entry point is used correctly.
284If you forget to set the entry point correctly in glslangValidator (-e MyFancyEntryPoint),
285you will likely encounter this error message:
286
287```
288Cannot end a function before ending the current block.
289Likely cause: If this SPIR-V was created from glslang HLSL, make sure the entry point is valid.
290```
291
292##### Vertex/Fragment interface linking
293
294HLSL relies on semantics in order to effectively link together shader stages. In the SPIR-V generated by glslang, the transformation from HLSL to GLSL ends up looking like
295
296```c++
297struct VSOutput {
298   // SV_Position is rerouted to gl_Position
299   float4 position : SV_Position;
300   float4 coord : TEXCOORD0;
301};
302
303VSOutput main(...) {}
304```
305
306```c++
307struct VSOutput {
308   float4 coord;
309}
310layout(location = 0) out VSOutput _magicNameGeneratedByGlslang;
311```
312
313While this works, be aware of the type of the struct which is used in the vertex stage and the fragment stage.
314There may be issues if the structure type name differs in vertex stage and fragment stage.
315
316You can make use of the reflection interface to force the name of the struct type.
317
318```
319// Something like this for both vertex outputs and fragment inputs.
320compiler.set_name(varying_resource.base_type_id, "VertexFragmentLinkage");
321```
322
323Some platform may require identical variable name for both vertex outputs and fragment inputs. (for example MacOSX)
324to rename variable base on location, please add
325```
326--rename-interface-variable <in|out> <location> <new_variable_name>
327```
328
329#### HLSL source to legacy GLSL/ESSL
330
331HLSL tends to emit varying struct types to pass data between vertex and fragment.
332This is not supported in legacy GL/GLES targets, so to support this, varying structs are flattened.
333This is done automatically, but the API user might need to be aware that this is happening in order to support all cases.
334
335Modern GLES code like this:
336```c++
337struct Output {
338   vec4 a;
339   vec2 b;
340};
341out Output vout;
342```
343
344Is transformed into:
345```c++
346struct Output {
347   vec4 a;
348   vec2 b;
349};
350varying vec4 Output_a;
351varying vec2 Output_b;
352```
353
354Note that now, both the struct name and the member names will participate in the linking interface between vertex and fragment, so
355API users might want to ensure that both the struct names and member names match so that vertex outputs and fragment inputs can link properly.
356
357
358#### Separate image samplers (HLSL/Vulkan) for backends which do not support it (GLSL)
359
360Another thing you need to remember is when using samplers and textures in HLSL these are separable, and not directly compatible with GLSL. If you need to use this with desktop GL/GLES, you need to call `Compiler::build_combined_image_samplers` first before calling `Compiler::compile`, or you will get an exception.
361
362```c++
363// From main.cpp
364// Builds a mapping for all combinations of images and samplers.
365compiler->build_combined_image_samplers();
366
367// Give the remapped combined samplers new names.
368// Here you can also set up decorations if you want (binding = #N).
369for (auto &remap : compiler->get_combined_image_samplers())
370{
371   compiler->set_name(remap.combined_id, join("SPIRV_Cross_Combined", compiler->get_name(remap.image_id),
372            compiler->get_name(remap.sampler_id)));
373}
374```
375
376If your target is Vulkan GLSL, `--vulkan-semantics` will emit separate image samplers as you'd expect.
377The command line client calls `Compiler::build_combined_image_samplers` automatically, but if you're calling the library, you'll need to do this yourself.
378
379#### Descriptor sets (Vulkan GLSL) for backends which do not support them (HLSL/GLSL/Metal)
380
381Descriptor sets are unique to Vulkan, so make sure that descriptor set + binding is remapped to a flat binding scheme (set always 0), so that other APIs can make sense of the bindings.
382This can be done with `Compiler::set_decoration(id, spv::DecorationDescriptorSet)`.
383
384#### Linking by name for targets which do not support explicit locations (legacy GLSL/ESSL)
385
386Modern GLSL and HLSL sources (and SPIR-V) relies on explicit layout(location) qualifiers to guide the linking process between shader stages,
387but older GLSL relies on symbol names to perform the linking. When emitting shaders with older versions, these layout statements will be removed,
388so it is important that the API user ensures that the names of I/O variables are sanitized so that linking will work properly.
389The reflection API can rename variables, struct types and struct members to deal with these scenarios using `Compiler::set_name` and friends.
390
391#### Clip-space conventions
392
393SPIRV-Cross can perform some common clip space conversions on gl_Position/SV_Position by enabling `CompilerGLSL::Options.vertex.fixup_clipspace`.
394While this can be convenient, it is recommended to modify the projection matrices instead as that can achieve the same result.
395
396For GLSL targets, enabling this will convert a shader which assumes `[0, w]` depth range (Vulkan / D3D / Metal) into `[-w, w]` range.
397For MSL and HLSL targets, enabling this will convert a shader in `[-w, w]` depth range (OpenGL) to `[0, w]` depth range.
398
399By default, the CLI will not enable `fixup_clipspace`, but in the API you might want to set an explicit value using `CompilerGLSL::set_options()`.
400
401Y-flipping of gl_Position and similar is also supported.
402The use of this is discouraged, because relying on vertex shader Y-flipping tends to get quite messy.
403To enable this, set `CompilerGLSL::Options.vertex.flip_vert_y` or `--flip-vert-y` in CLI.
404
405#### Reserved identifiers
406
407When cross-compiling, certain identifiers are considered to be reserved by the implementation.
408Code generated by SPIRV-Cross cannot emit these identifiers as they are reserved and used for various internal purposes,
409and such variables will typically show up as `_RESERVED_IDENTIFIER_FIXUP_`
410or some similar name to make it more obvious that an identifier has been renamed.
411
412Reflection output will follow the exact name specified in the SPIR-V module. It might not be a valid identifier in the C sense,
413as it may contain non-alphanumeric/non-underscore characters.
414
415Reserved identifiers currently assumed by the implementation are (in pseudo-regex):
416
417- _$digit+, e.g. `_100`, `_2`
418- _$digit+_.+, e.g. `_100_tmp`, `_2_foobar`. `_2Bar` is **not** reserved.
419- gl_- prefix
420- spv- prefix
421- SPIRV_Cross prefix. This prefix is generally used for interface variables where app needs to provide data for workaround purposes.
422  This identifier will not be rewritten, but be aware of potential collisions.
423- Double underscores (reserved by all target languages).
424
425Members of structs also have a reserved identifier:
426- _m$digit+$END, e.g. `_m20` and `_m40` are reserved, but not `_m40Foobar`.
427
428## Contributing
429
430Contributions to SPIRV-Cross are welcome. See Testing and Licensing sections for details.
431
432### Testing
433
434SPIRV-Cross maintains a test suite of shaders with reference output of how the output looks after going through a roundtrip through
435glslangValidator/spirv-as then back through SPIRV-Cross again.
436The reference files are stored inside the repository in order to be able to track regressions.
437
438All pull requests should ensure that test output does not change unexpectedly. This can be tested with:
439
440```
441./checkout_glslang_spirv_tools.sh # Checks out glslang and SPIRV-Tools at a fixed revision which matches the reference output.
442                                  # NOTE: Some users have reported problems cloning from git:// paths. To use https:// instead pass in
443                                  # $ PROTOCOL=https ./checkout_glslang_spirv_tools.sh
444                                  # instead.
445./build_glslang_spirv_tools.sh    # Builds glslang and SPIRV-Tools.
446./test_shaders.sh                 # Runs over all changes and makes sure that there are no deltas compared to reference files.
447```
448
449`./test_shaders.sh` currently requires a Makefile setup with GCC/Clang to be set up.
450However, on Windows, this can be rather inconvenient if a MinGW environment is not set up.
451To use a spirv-cross binary you built with CMake (or otherwise), you can pass in an environment variable as such:
452
453```
454SPIRV_CROSS_PATH=path/to/custom/spirv-cross ./test_shaders.sh
455```
456
457However, when improving SPIRV-Cross there are of course legitimate cases where reference output should change.
458In these cases, run:
459
460```
461./update_test_shaders.sh          # SPIRV_CROSS_PATH also works here.
462```
463
464to update the reference files and include these changes as part of the pull request.
465Always make sure you are running the correct version of glslangValidator as well as SPIRV-Tools when updating reference files.
466See `checkout_glslang_spirv_tools.sh` which revisions are currently expected. The revisions change regularly.
467
468In short, the master branch should always be able to run `./test_shaders.py shaders` and friends without failure.
469SPIRV-Cross uses Travis CI to test all pull requests, so it is not strictly needed to perform testing yourself if you have problems running it locally.
470A pull request which does not pass testing on Travis will not be accepted however.
471
472When adding support for new features to SPIRV-Cross, a new shader and reference file should be added which covers usage of the new shader features in question.
473Travis CI runs the test suite with the CMake, by running `ctest`. This is a more straight-forward alternative to `./test_shaders.sh`.
474
475### Licensing
476
477Contributors of new files should add a copyright header at the top of every new source code file with their copyright
478along with the Apache 2.0 licensing stub.
479
480### Formatting
481
482SPIRV-Cross uses `clang-format` to automatically format code.
483Please use `clang-format` with the style sheet found in `.clang-format` to automatically format code before submitting a pull request.
484
485To make things easy, the `format_all.sh` script can be used to format all
486source files in the library. In this directory, run the following from the
487command line:
488
489	./format_all.sh
490
491## Regression testing
492
493In shaders/ a collection of shaders are maintained for purposes of regression testing.
494The current reference output is contained in reference/.
495`./test_shaders.py shaders` can be run to perform regression testing.
496
497See `./test_shaders.py --help` for more.
498
499### Metal backend
500
501To test the roundtrip path GLSL -> SPIR-V -> MSL, `--msl` can be added, e.g. `./test_shaders.py --msl shaders-msl`.
502
503### HLSL backend
504
505To test the roundtrip path GLSL -> SPIR-V -> HLSL, `--hlsl` can be added, e.g. `./test_shaders.py --hlsl shaders-hlsl`.
506
507### Updating regression tests
508
509When legitimate changes are found, use `--update` flag to update regression files.
510Otherwise, `./test_shaders.py` will fail with error code.
511
512### Mali Offline Compiler cycle counts
513
514To obtain a CSV of static shader cycle counts before and after going through spirv-cross, add
515`--malisc` flag to `./test_shaders`. This requires the Mali Offline Compiler to be installed in PATH.
516
517